Výkon architektury integrace CLR
platí pro:SQL Serverazure SQL Managed Instance
Tento článek popisuje některé z možností návrhu, které zlepšují výkon integrace SQL Serveru s modulem CLR (Common Language Runtime) rozhraní .NET Framework.
Proces kompilace
Při kompilaci výrazů SQL se při výskytu odkazu na spravovanou rutinu vygeneruje běžný zástupný znak CIL (Intermediate Language). Tato procedura obsahuje kód pro zařazování rutinních parametrů z SQL Serveru do MODULU CLR, vyvolání funkce a vrácení výsledku. Tento připevnit kód je založen na typu parametru a směru parametru (v, vennebo odkaz).
Připevnit kód umožňuje optimalizace specifické pro typ a zajišťuje efektivní vynucování sémantiky SQL Serveru, jako je nullability, omezující omezující vlastnosti, by-value a standardní zpracování výjimek. Generováním kódu pro přesné typy argumentů se vyhnete nákladům na vytvoření objektu typu nebo obálky (tzv. boxing) přes hranice vyvolání.
Vygenerovaná procedura se pak zkompiluje do nativního kódu a optimalizuje se pro konkrétní hardwarovou architekturu, na které se SQL Server spouští, pomocí služeb kompilace ZA běhu (JIT) modulu CLR. Služby JIT se vyvolávají na úrovni metody a umožňují hostitelskému prostředí SQL Serveru vytvořit jednu kompilační jednotku, která zahrnuje spouštění SQL Serveru i CLR. Jakmile je zástupný kód zkompilován, výsledný ukazatel funkce se stane implementací funkce za běhu. Tento přístup ke generování kódu zajišťuje, že v době běhu nejsou k dispozici žádné dodatečné náklady na vyvolání související s reflexí nebo přístupem k metadatům.
Rychlé přechody mezi SQL Serverem a CLR
Proces kompilace poskytuje ukazatel funkce, který lze volat za běhu z nativního kódu. U skalárních uživatelem definovaných funkcí probíhá vyvolání této funkce na jednotlivých řádech. Aby se minimalizovaly náklady na přechod mezi SQL Serverem a CLR, příkazy, které obsahují jakékoli spravované vyvolání, mají spouštěcí krok k identifikaci domény cílové aplikace. Tento krok identifikace snižuje náklady na přechod pro každý řádek.
Důležité informace o výkonu
Následující část shrnuje aspekty výkonu specifické pro integraci CLR v SQL Serveru. Další informace naleznete v tématu Použití integrace CLR v SQL Server 2005. Informace o výkonu spravovaného kódu naleznete v tématu Zlepšení výkonu a škálovatelnosti aplikací .NET.
Uživatelem definované funkce
Funkce CLR využívají rychlejší cestu volání než Transact-SQL uživatelem definované funkce. Spravovaný kód má navíc rozhodující výhodu výkonu oproti Transact-SQL z hlediska procedurálního kódu, výpočtu a manipulace s řetězci. Funkce CLR, které jsou náročné na výpočetní výkon a které neprovádějí přístup k datům, jsou lépe napsané ve spravovaném kódu. Transact-SQL funkce však provádějí přístup k datům efektivněji než integrace CLR.
Uživatelem definované agregace
Spravovaný kód může výrazně převýšit agregaci založenou na kurzorech. Spravovaný kód obvykle provádí o něco pomaleji než předdefinované agregační funkce SQL Serveru. Pokud existuje nativní integrovaná agregační funkce, doporučujeme ji použít. V případech, kdy potřebná agregace není nativně podporovaná, zvažte z důvodů výkonu agregaci definovanou uživatelem definovanou clr přes implementaci založenou na kurzorech.
Streamované funkce hodnotné tabulkou
Aplikace často potřebují v důsledku vyvolání funkce vrátit tabulku. Mezi příklady patří čtení tabulkových dat ze souboru jako součást operace importu a převod hodnot oddělených čárkami na relační reprezentaci. Obvykle toho můžete dosáhnout materializací a naplněním tabulky výsledků, než ji volající spotřebuje. Integrace MODULU CLR do SQL Serveru zavádí nový mechanismus rozšiřitelnosti označovaný jako funkce STVF (streaming table-valued). Spravované STVF fungují lépe než srovnatelné implementace rozšířených uložených procedur.
STVFs jsou spravované funkce, které vrací IEnumerable
rozhraní.
IEnumerable
obsahuje metody pro navigaci v sadě výsledků vrácených STVF. Při vyvolání STVF se vrácená IEnumerable
přímo připojí k plánu dotazu. Plán dotazu volá IEnumerable
metody, když potřebuje načíst řádky. Tento model iterace umožňuje využívat výsledky okamžitě po vytvoření prvního řádku, a nečekejte na naplnění celé tabulky. Také výrazně snižuje využití paměti vyvoláním funkce.
Matice vs. kurzory
Když Transact-SQL kurzory musí procházet data, která jsou snadněji vyjádřena jako pole, lze spravovaný kód použít s významnými nárůsty výkonu.
Řetězcová data
Data znaků SQL Serveru, například varchar, mohou být typu SqlString
nebo SqlChars
ve spravovaných funkcích.
SqlString
proměnných vytvoří instanci celé hodnoty do paměti.
SqlChars
proměnné poskytují rozhraní streamování, které lze použít k dosažení lepšího výkonu a škálovatelnosti tím, že nevytvoření instance celé hodnoty do paměti. To je důležité pro data velkých objektů (LOB). Kromě toho lze k datům XML serveru přistupovat prostřednictvím rozhraní streamování vráceného SqlXml.CreateReader()
.
CLR vs. rozšířené uložené procedury
Rozhraní API (Microsoft.SqlServer.Server
aplikačních programovacích rozhraní), která umožňují spravovaným procedurám odesílat sady výsledků zpět klientovi, fungují lépe než rozhraní API odS (Open Data Services) používaná rozšířenými uloženými procedurami. Rozhraní API System.Data.SqlServer
navíc podporují datové typy, jako jsou xml, varchar(max), nvar(max)a varbinary(max), zatímco rozhraní API ODS nebyla rozšířena tak, aby podporovala tyto datové typy.
Pomocí spravovaného kódu spravuje SQL Server použití prostředků, jako jsou paměť, vlákna a synchronizace. Důvodem je to, že spravovaná rozhraní API, která tyto prostředky zpřístupňují, se implementují nad správcem prostředků SQL Serveru. Sql Server naopak nemá žádné zobrazení nebo kontrolu nad používáním prostředků rozšířené uložené procedury. Pokud například rozšířená uložená procedura spotřebovává příliš mnoho prostředků procesoru nebo paměti, neexistuje způsob, jak to zjistit nebo řídit s SQL Serverem. U spravovaného kódu ale SQL Server dokáže zjistit, že dané vlákno dlouhou dobu nepřineslo, a pak vynutit, aby úloha byla poskytnuta tak, aby se dala naplánovat jiná práce. Použití spravovaného kódu tedy poskytuje lepší škálovatelnost a využití systémových prostředků.
Spravovaný kód může mít další režii potřebnou k údržbě spouštěcího prostředí a provádění kontrol zabezpečení. Jedná se například o případ, kdy běží uvnitř SQL Serveru a vyžaduje se mnoho přechodů ze spravovaného na nativní kód (protože SQL Server potřebuje provést další údržbu nastavení specifických pro vlákna při přesunu do nativního kódu a zpět). Rozšířené uložené procedury tedy můžou výrazně zesílit spravovaný kód spuštěný uvnitř SQL Serveru pro případy, kdy mezi spravovaným a nativním kódem dochází k častým přechodům.
Poznámka
Nevyvíjejte nové rozšířené uložené procedury, protože tato funkce je zastaralá.
Nativní serializace pro uživatelem definované typy
Uživatelsky definované typy (UDT) jsou navrženy jako mechanismus rozšiřitelnosti systému skalárních typů. SQL Server implementuje formát serializace pro UDT označované jako Format.Native
. Během kompilace je struktura typu zkoumána tak, aby vygenerovala soubor CIL, který je přizpůsobený pro danou definici typu.
Nativní serializace je výchozí implementace sql Serveru. Serializace definovaná uživatelem vyvolá metodu definovanou autorem typu k serializaci.
Format.Native
serializace by měla být použita, pokud je to možné pro nejlepší výkon.
Normalizace srovnatelných UDT
Relační operace, jako je řazení a porovnávání UDT, pracují přímo s binární reprezentací hodnoty. Toho dosáhnete uložením normalizované (binární seřazené) reprezentace stavu UDT na disku.
Normalizace má dvě výhody:
Operace porovnání je výrazně levnější tím, že se zabrání konstrukci instance typu a režijní režie vyvolání metody.
Vytvoří binární doménu pro UDT, která umožňuje vytváření histogramů, indexů a histogramů pro hodnoty typu.
Normalizované UDT tedy mají podobný profil výkonu jako nativní předdefinované typy operací, které nezahrnují vyvolání metody.
Škálovatelné využití paměti
Aby bylo možné spravované uvolňování paměti správně provádět a škálovat v SQL Serveru, vyhněte se velkému a jedinému přidělení. Přidělení větší než 88 kilobajtů (kB) se umístí do haldy velkého objektu, což způsobí, že uvolňování paměti bude provádět a škálovat horší než mnoho menších přidělení. Pokud například potřebujete přidělit velké multidimenzionální pole, je lepší přidělit agregované (bodové) pole.