Архитектура интеграции со средой CLR — производительностьCLR Integration Architecture - Performance

ОБЛАСТЬ ПРИМЕНЕНИЯ: даSQL Server нетБаза данных SQL AzureнетХранилище данных SQL AzureнетParallel Data WarehouseAPPLIES TO: yesSQL Server noAzure SQL Database noAzure SQL Data Warehouse noParallel Data Warehouse

В этом разделе рассматриваются некоторые варианты проектирования, которые повышают производительность MicrosoftMicrosoft SQL ServerSQL Server интеграция с MicrosoftMicrosoft .NET Framework среда CLR (CLR).This topic discusses some of the design choices that enhance the performance of MicrosoftMicrosoft SQL ServerSQL Server integration with the MicrosoftMicrosoft .NET Framework common language runtime (CLR).

Процесс компиляцииThe Compilation Process

Во время компиляции выражений SQL, когда обнаруживается ссылка на управляемую процедуру MicrosoftMicrosoft создается заглушка на промежуточном языке (MSIL).During compilation of SQL expressions, when a reference to a managed routine is encountered, a MicrosoftMicrosoft intermediate language (MSIL) stub is generated. Заглушка содержит программный код для упаковки параметров процедуры из SQL ServerSQL Server в среду CLR, вызова функции и возвращения результата.This stub includes code to marshal the routine parameters from SQL ServerSQL Server to the CLR, invoke the function, and return the result. Этот связующий код основан на типе параметра и его направлении (входной, выходной, передача по ссылке).This "glue" code is based on the type of parameter and on parameter direction (in, out, or reference).

Связующий код позволяет проводить оптимизацию для конкретного типа и гарантирует эффективное обеспечение семантики SQL ServerSQL Server таких свойств, как допустимость значений NULL, ограничивающие аспекты, передача параметров по значению и стандартная обработка исключений.The glue code enables type-specific optimizations and ensures efficient enforcement of SQL ServerSQL Server semantics, such as nullability, constraining facets, by-value, and standard exception handling. Создавая код для конкретных типов аргументов, можно избежать приведения типов и нагрузки по созданию объектов-оболочек (этот процесс называют также «упаковкой») при вызове, пересекающем границы процессов.By generating code for the exact types of the arguments, you avoid type coercion or wrapper object creation costs (called "boxing") across the invocation boundary.

Затем созданная заглушка компилируется в собственный код и оптимизируется для конкретной аппаратной архитектуры, на которой выполняется SQL ServerSQL Server, с использованием служб JIT-компиляции среды CLR.The generated stub is then compiled to native code and optimized for the particular hardware architecture on which SQL ServerSQL Server executes, using the JIT (just-in-time) compilation services of the CLR. JIT-службы вызываются на уровне методов и позволяют управляющему окружению SQL ServerSQL Server создавать единый объект компиляции между СУБД SQL ServerSQL Server и выполнением в среде CLR.The JIT services are invoked at the method level and allow the SQL ServerSQL Server hosting environment to create a single compilation unit that spans both SQL ServerSQL Server and CLR execution. После компиляции заглушки результирующий указатель на функцию становится реализацией этой функции времени выполнения.Once the stub is compiled, the resulting function pointer becomes the run-time implementation of the function. Такой подход к созданию кода гарантирует отсутствие лишних расходов по вызову функций, связанных с отражением или доступом к метаданным во время выполнения.This code generation approach ensures that there are no additional invocation costs related to reflection or metadata access at run time.

Быстрые переходы между СУБД SQL Server и средой CLRFast Transitions Between SQL Server and CLR

Процесс компиляции возвращает указатель на функцию, с помощью которого можно вызвать функцию во время выполнения из машинного кода.The compilation process yields a function pointer that can be called at run time from native code. Для определяемых пользователем скалярных функций этот вызов функции происходит по строкам.In the case of scalar-valued user-defined functions, this function invocation happens on a per-row basis. Для максимального снижения стоимости перехода между SQL ServerSQL Server и средой CLR все инструкции, содержащие вызов управляемого кода, проделывают начальный шаг для выявления целевого домена приложения.To minimize the cost of transitioning between SQL ServerSQL Server and the CLR, statements that contain any managed invocation have a startup step to identify the target application domain. Этот шаг идентификации снижает стоимость перехода для каждой строки.This identification step reduces the cost of transitioning for each row.

Вопросы производительностиPerformance Considerations

Далее проводится краткое перечисление факторов производительности, специфичных для интеграции со средой CLR и SQL ServerSQL Server.The following summarizes performance considerations specific to CLR integration in SQL ServerSQL Server. Более подробные сведения можно найти в "с помощью интеграции со средой CLR в SQL Server 2005" на сайте MSDN.More detailed information can be found in "Using CLR Integration in SQL Server 2005" on the MSDN Web site. Общие сведения о производительности управляемого кода можно найти в "повышение производительности приложений .NET и масштабируемости" на сайте MSDN.General information regarding managed code performance can be found in "Improving .NET Application Performance and Scalability" on the MSDN Web site.

Определяемые пользователем функцииUser-Defined Functions

Функции CLR используют ускоренный путь вызова по сравнению с определяемыми пользователем функциями в Transact-SQLTransact-SQL.CLR functions benefit from a quicker invocation path than that of Transact-SQLTransact-SQL user-defined functions. Кроме того, производительность управляемого кода заметно выше, чем у Transact-SQLTransact-SQL, в том, что касается процедурного кода, вычислений и операций со строками.Additionally, managed code has a decisive performance advantage over Transact-SQLTransact-SQL in terms of procedural code, computation, and string manipulation. Функции CLR, которые требуют большого объема вычислений и не требуют доступа к данным, лучше писать в управляемом коде.CLR functions that are computing-intensive and that do not perform data access are better written in managed code. Однако функции Transact-SQLTransact-SQL осуществляют доступ к данным более эффективно, чем функции интеграции со средой CLR.Transact-SQLTransact-SQL functions do, however, perform data access more efficiently than CLR integration.

Определяемые пользователем статистические функцииUser-Defined Aggregates

Управляемый код может значительно опережать по производительности статическую обработку на основе курсора.Managed code can significantly outperform cursor-based aggregation. Управляемый код обычно работает несколько медленнее, чем встроенные агрегатные функции SQL ServerSQL Server.Managed code generally performs slightly slower than built-in SQL ServerSQL Server aggregate functions. Если существует собственная встроенная агрегатная функция SQL Server, рекомендуется использовать ее.We recommend that if a native built-in aggregate function exists, you should use it. В случаях, когда нужные статистические вычисления не поддерживаются встроенными функциями, из соображений производительности можно использовать созданную пользователем статистическую функцию среды CLR, реализованную на основе курсора.In cases in which the needed aggregation is not natively supported, consider a CLR user-defined aggregate over a cursor-based implementation for performance reasons.

Функции потока с табличным значениемStreaming Table-Valued Functions

Часто бывает нужно, чтобы в результате вызова функции приложение вернуло таблицу.Applications often need to return a table as a result of invoking a function. Например, в качестве части операции импорта приложение читает табличные данные из файла; нужно преобразовать их из формата величин с разделителями-запятыми в реляционное представление.Examples include reading tabular data from a file as part of an import operation, and converting comma-separated-values to a relational representation. Обычно это достигается с помощью материализации и заполнения таблицы результатов до ее использования вызывающим объектом.Typically, you can accomplish this by materializing and populating the result table before it can be consumed by the caller. Интеграция CLR в SQL ServerSQL Server использует новый механизм расширяемости — функции потока с табличным значением (streaming table-valued function, STVF).The integration of the CLR into SQL ServerSQL Server introduces a new extensibility mechanism called a streaming table-valued function (STVF). Управляемые функции потока, возвращающие табличное значение, по производительности опережают реализации на основе расширенных хранимых процедур.Managed STVFs perform better than comparable extended stored procedure implementations.

Потоковые, функции, возвращающие IEnumerable интерфейс.STVFs are managed functions that return an IEnumerable interface. IEnumerable есть методы для навигации результирующего набора, возвращенного функцией STVF.IEnumerable has methods to navigate the result set returned by the STVF. При вызове Возвращающей возвращенного IEnumerable подключен напрямую к плану запроса.When the STVF is invoked, the returned IEnumerable is directly connected to the query plan. Вызовы план запроса IEnumerable методы при необходимости для получения строк.The query plan calls IEnumerable methods when it needs to fetch rows. Такая модель итерации позволяет провести немедленную обработку результатов сразу после получения первой строки, не ожидая заполнения всей таблицы.This iteration model allows results to be consumed immediately after the first row is produced, instead of waiting until the entire table is populated. Она также существенно снижает затраты памяти на вызов функции.It also significantly reduces the memory consumed by invoking the function.

Сравнение массивов и. КурсорыArrays vs. Cursors

Если курсорам Transact-SQLTransact-SQL нужно перемещаться по данным, которые проще реализовать как массив, использование управляемого кода принесет существенный выигрыш в производительности.When Transact-SQLTransact-SQL cursors must traverse data that is more easily expressed as an array, managed code can be used with significant performance gains.

Строковые данныеString Data

SQL ServerSQL Server символьные данные, такие как varchar, может быть типа SqlString или SqlChars в управляемых функций.character data, such as varchar, can be of the type SqlString or SqlChars in managed functions. Переменные типа SqlString создают в памяти экземпляр всего значения целиком.SqlString variables create an instance of the entire value into memory. Переменные типа SqlChars обеспечивают потоковый интерфейс, который позволяет добиться более высокой производительности и масштабируемости, так как не создает в памяти экземпляра всего значения сразу.SqlChars variables provide a streaming interface that can be used to achieve better performance and scalability by not creating an instance of the entire value into memory. Это особенно важно для типов больших объектов (LOB).This becomes particularly important for large object (LOB) data. Кроме того, XML-данных может осуществляться через интерфейс потоковой передачи, возвращенный SqlXml.CreateReader() .Additionally, server XML data can be accessed through a streaming interface returned by SqlXml.CreateReader().

Сравнение CLR и. Расширенные хранимые процедурыCLR vs. Extended Stored Procedures

API-интерфейсы Microsoft.SqlServer.Server, позволяющие управляемым процедурам отсылать результирующие наборы обратно клиенту, имеют более высокую производительность, чем API-интерфейсы служб Open Data Services (ODS), используемые расширенными хранимыми процедурами.The Microsoft.SqlServer.Server application programming interfaces (APIs) that allow managed procedures to send result sets back to the client perform better than the Open Data Services (ODS) APIs used by extended stored procedures. Кроме того, такие как типы данных поддержки API-интерфейсы System.Data.SqlServer xml, varchar(max) , nvarchar(max) , и varbinary(max) , включенная в SQL Server 2005 (9.x)SQL Server 2005 (9.x), тогда как в ODS API-не были расширены для поддержки новых типов данных.Furthermore, the System.Data.SqlServer APIs support data types such as xml, varchar(max), nvarchar(max), and varbinary(max), introduced in SQL Server 2005 (9.x)SQL Server 2005 (9.x), while the ODS APIs have not been extended to support the new data types.

При использовании управляемого кода SQL ServerSQL Server управляет использованием ресурсов памяти, потоков и синхронизации.With managed code, SQL ServerSQL Server manages use of resources such as memory, threads, and synchronization. Это происходит потому, что управляемые API-интерфейсы, предоставляющие доступ к этим ресурсам, реализованы поверх диспетчера ресурсов SQL ServerSQL Server.This is because the managed APIs that expose these resources are implemented on top of the SQL ServerSQL Server resource manager. SQL ServerSQL Server, напротив, не может управлять использованием ресурсов расширенных хранимых процедур.Conversely, SQL ServerSQL Server has no view or control over the resource usage of the extended stored procedure. Например, если расширенная хранимая процедура потребляет слишком много ресурсов процессора или памяти, в SQL ServerSQL Server нет никаких средств, чтобы это обнаружить или управлять этим.For example, if an extended stored procedure consumes too much CPU or memory resources, there is no way to detect or control this with SQL ServerSQL Server. Напротив, при использовании управляемого кода SQL ServerSQL Server может увидеть, что конкретный поток давно не отдает управление, и заставить задачу отдать управление, чтобы можно было планировать выполнение других задач.With managed code, however, SQL ServerSQL Server can detect that a given thread has not yielded for a long period of time, and then force the task to yield so that other work can be scheduled. Поэтому использование управляемого кода позволяет лучше масштабировать выполнение и оптимизировать использование системных ресурсов.Consequently, using managed code provides for better scalability and system resource usage.

Управляемый код может вызывать дополнительные расходы на поддержку среды выполнения и проверки безопасности.Managed code may incur additional overhead necessary to maintain the execution environment and perform security checks. Это происходит, например, при выполнении внутри SQL ServerSQL Server, когда требуются многочисленные переходы от управляемого кода к собственному и обратно (потому что SQL ServerSQL Server вынужден проводить дополнительное обслуживание настроек конкретных потоков при переходе к машинному коду и обратно).This is the case, for example, when running inside SQL ServerSQL Server and numerous transitions from managed to native code are required (because SQL ServerSQL Server needs to do additional maintenance on thread-specific settings when moving out to native code and back). Следовательно, расширенные хранимые процедуры могут выполняться значительно быстрее управляемого кода внутри SQL ServerSQL Server в случаях, когда требуются многочисленные переходы от управляемого к машинному коду и обратно.Consequently, extended stored procedures can significantly outperform managed code running inside SQL ServerSQL Server for cases in which there are frequent transitions between managed and native code.

Примечание

Не рекомендуется разрабатывать новые расширенные хранимые процедуры, поскольку эта функциональная возможность устарела.It is recommended that you do not develop new extended stored procedures, because this feature has been deprecated.

Собственная сериализация для определяемых пользователем типовNative Serialization for User-Defined Types

Определяемые пользователем типы (UDT) представляют собой механизм расширения скалярной системы типов.User-defined types (UDTs) are designed as an extensibility mechanism for the scalar type system. SQL ServerSQL Server реализован формат сериализации для определяемого пользователем типа — Format.Native.implements a serialization format for UDTs called Format.Native. Во время компиляции исследуется структура типа, а затем создается код MSIL, настраиваемый для данного конкретного определения типа.During compilation, the structure of the type is examined to generate MSIL that is customized for that particular type definition.

Собственная сериализация используется в SQL ServerSQL Server по умолчанию.Native serialization is the default implementation for SQL ServerSQL Server. Сериализация, определяемая пользователем, вызывает для сериализации метод, указанный автором типа.User-defined serialization invokes a method defined by the type author to do the serialization. Format.Native следует использовать по возможности для повышения производительности.Format.Native serialization should be used when possible for best performance.

Нормализация сравнимых определяемых пользователем типовNormalization of Comparable UDTs

Операции отношения, например сортировка и сравнение определяемых пользователем типов, работают непосредственно с двоичным представлением значения.Relational operations, such as sorting and comparing UDTs, operate directly on the binary representation of the value. Для этого на диске хранится нормализованное (двоичное, упорядоченное) представление состояния определяемого пользователем типа.This is accomplished by storing a normalized (binary ordered) representation of the state of the UDT on disk.

Нормализация имеет два преимущества: ее использование значительно «удешевляет» операцию сравнения, так как избавляет от необходимости создания экземпляра типа и вызова метода; кроме того, нормализация создает двоичное представление определяемого пользователем типа, что позволяет строить гистограммы, индексы и гистограммы для значений этого типа.Normalization has two benefits: it makes the comparison operation considerably less expensive by avoiding the construction of the type instance and the method invocation overhead; and it creates a binary domain for the UDT, enabling the construction of histograms, indexes, and histograms for values of the type. Поэтому производительность операций с нормализованными определяемыми пользователем типами почти такая же, как у операций, не требующих вызова методов, над встроенными типами.Consequently, normalized UDTs have a very similar performance profile to the native built-in types for operations that do not involve method invocation.

Масштабируемое использование памятиScalable Memory Usage

Чтобы управляемая сборка мусора в SQL ServerSQL Server имела высокую производительность и хорошо масштабировалась, следует избегать выделения памяти одним большим блоком.In order for managed garbage collection to perform and scale well in SQL ServerSQL Server, avoid large, single allocation. Выделенные области памяти размером больше 88 КБ помещаются в кучу для больших объектов, для которой сборка мусора работает гораздо медленнее и хуже масштабируется, чем для небольших областей памяти.Allocations greater than 88 kilobytes (KB) in size will be placed on the Large Object Heap, which will cause garbage collection to perform and scale much worse than many smaller allocations. Например, если нужно выделить память для большого многомерного массива, лучше выделить память под массив массивов (разреженный массив).For example, if you need to allocate a large multi-dimensional array, it is better to allocate a jagged (scattered) array.

См. такжеSee Also

Определяемые пользователем типы в CLRCLR User-Defined Types