sql >> Databáze >  >> RDS >> Sqlserver

Jaká je při provádění uložené procedury výhoda použití CommandType.StoredProcedure oproti použití CommandType.Text?

Podle testů v tomto blogovém příspěvku SQL Server provede parametrizaci za vás zabalením vašeho příkazu do sp_executesql, když použijete CommandType.Text . Ale když použijete CommandType.StoredProcedure budete ji parametrizovat a tím databázi ušetříte práci. Druhá metoda je rychlejší.

Upravit:

Nastavení

Sám jsem provedl nějaké testy a zde jsou výsledky.

Vytvořte tento postup:

create procedure dbo.Test
(
   @Text1 varchar(10) = 'Default1'
  ,@Text2 varchar(10) = 'Default2'
)
as
begin
   select @Text1 as Text1, @Text2 as Text2
end

Přidejte k němu trasování pomocí SQL Server Profiler.

A pak jej zavolejte pomocí následujícího kódu:

using System;
using System.Data;
using System.Data.SqlClient;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main()
        {
            CallProcedure( CommandType.Text );
            CallProcedure( CommandType.StoredProcedure );
        }

        private static void CallProcedure(CommandType commandType)
        {
            using ( SqlConnection connection = new SqlConnection("Data Source=localhost;Initial Catalog=Test;Integrated Security=SSPI;") )
            {
                connection.Open();
                using ( SqlCommand textCommand = new SqlCommand("dbo.Test", connection) )
                {
                    textCommand.CommandType = commandType;
                    textCommand.Parameters.AddWithValue("@Text1", "Text1");
                    textCommand.Parameters.AddWithValue("@Text2", "Text2");
                    using ( IDataReader reader = textCommand.ExecuteReader() )
                    {
                        while ( reader.Read() )
                        {
                            Console.WriteLine(reader["Text1"] + " " + reader["Text2"]);
                        }
                    }
                }
            }
        }
    }
}

Výsledky

V obou případech jsou hovory prováděny pomocí RPC.

Zde je to, co trasování odhalí pomocí CommandType.Text :

exec sp_executesql N'dbo.Test',N'@Text1 nvarchar(5),@Text2 nvarchar(5)',@Text1=N'Text1',@Text2=N'Text2'

A zde je výsledek pomocí CommandType.StoredProcedure :

exec dbo.Test @Text1=N'Text1',@Text2=N'Text2'

Jak můžete vidět, textové volání je zabaleno do volání sp_executesql aby byl správně parametrizován. To samozřejmě způsobí mírnou režii, a tudíž mé předchozí tvrzení, že použití CommandType.StoredProcedure je rychlejší stále stojí.

Další věc, která stojí za zmínku, a která je zde také určitým způsobem narušující dohodu, je to, že když jsem vytvořil proceduru bez výchozích hodnot, dostal jsem následující chybu:

Zpráva 201, Úroveň 16, Stav 4, Test procedury, řádek 0 Procedura nebo funkce 'Test' očekává parametr '@Text1', který nebyl dodán.

Důvodem je způsob volání sp_executesql je vytvořen, jak vidíte, parametry jsou deklarovány a inicializovány, ale nejsou použity . Aby hovor fungoval, měl vypadat takto:

exec sp_executesql N'dbo.Test @Text1, @Text2',N'@Text1 nvarchar(5),@Text2 nvarchar(5)',@Text1=N'Text1',@Text2=N'Text2'

To znamená, když používáte CommandType.Text musíte přidat parametry do CommandText pokud nechcete, aby byly vždy použity výchozí hodnoty.

Abych tedy odpověděl na vaši otázku

  1. Pomocí CommandType.StoredProcedure je rychlejší.
  2. Pokud používáte CommandType.Text , pak budete muset přidat názvy parametrů do volání procedury, pokud nechcete, aby byly použity výchozí hodnoty.


  1. Jak zobrazit chybu dotazu v PDO PHP

  2. ORA-00054:zdroj je zaneprázdněn a získává se specifikací NOWAIT

  3. SQLite JSON_REMOVE()

  4. Porovnání Load Balancerů pro PostgreSQL