Неявное преобразование, что это?
Пересказ статьи Monica Rathbun. What is Implicit Conversion?
Это еще одна небольшая публикация по поводу простых изменений, которые вы можете сделать в своем коде, чтобы получить более оптимальный план выполнения. На этот раз речь пойдет о неявных преобразованиях. Неявное преобразование происходит, когда SQL Server должен автоматически преобразовать данные из одного типа в другой при сравнении значений, перемещении данных или комбинации одних значений с другими. Когда значения преобразуются в процессе обработки запроса, это добавляет излишнюю нагрузку, что влияет на производительность.
Вот замечательная схема от Microsoft, которая показывает допустимые преобразования типов, и какие из них требуют явного или неявного преобразования. В этой статье я не буду рассматривать явные преобразования, просто знайте, что они явно с помощью операторов CAST или COVERT указывают SQL Server, как преобразовать значение.
Давайте рассмотрим очень простой, но общий сценарий неявного преобразования. В нем таблица Employee содержит столбец NationalIDNumber, который определен на типе данных NVARCHAR. В запросе мы будем использовать предложение WHERE для поиска опреденного ID.
В нижеприведенном запросе мы запрашиваем NationalIDNumber, равный целому значению 14417807. Для сравнения этих двух типов данных SQL Server должен преобразовать NVARCHAR к INT. Это означает, что каждое значение в этом столбце должно пройти процесс преобразования, что вызывает сканирование таблицы (table scan).
В плане выполнения вы увидите восклицательный знак, предупреждающий, что в запросе имеется потенциальная проблема. Наведя курсор на оператор SELECT, можно увидеть, что происходит неявное преобразование (CONVERT_IMPLICIT), что может помешать оптимизатору использовать SEEK (поиск).
Вопрос - как исправить это. Это действительно просто, но потребует изменения кода. Давайте вернемся к нашему запросу.
Помните, что мы запрашивали целое значение. Простое добавление кавычек, ограничивающих значение, поможет нам решить проблему. Всегда важно знать, какого типа столбцы, которые вы используете в запросе. В данном примере, поскольку тип NVARCHAR, все, что необходимо сделать, это передать символьное значение. Это выполняется кавычками-ограничителями вокруг значения.
Просто посмотрим на результаты. Напомним, что выше мы имели число сканирований 1, логических чтений 9, физических чтений 0. Теперь при выполнении получим:
На графическом плане также видно, что предупреждение ушло, и мы имеем SEEK вместо SCAN, что значительно эффективней.
Имеется много способов, с помощью которых вы можете решить проблемы, связанные с неявными или явными преобразованиями и дополнительной нагрузкой, которую они создают. В большинстве случаев очень легко поправить ситуацию путем незначительных изменений в коде. Чтобы помочь вам найти их в вашей среде, Jonathan Kehayia написал запрос для нахождения столбцов с неявным преобразованием в кэше планов.
Давайте рассмотрим очень простой, но общий сценарий неявного преобразования. В нем таблица Employee содержит столбец NationalIDNumber, который определен на типе данных NVARCHAR. В запросе мы будем использовать предложение WHERE для поиска опреденного ID.
В нижеприведенном запросе мы запрашиваем NationalIDNumber, равный целому значению 14417807. Для сравнения этих двух типов данных SQL Server должен преобразовать NVARCHAR к INT. Это означает, что каждое значение в этом столбце должно пройти процесс преобразования, что вызывает сканирование таблицы (table scan).
USE AdventureWorks2016CTP3
GO
SET STATISTICS IO ON
GO
SELECT BusinessEntityID, NationalIDNumber, LoginID, HireDate,JobTitle
FROM HumanResources.Employee
WHERE NationalIDNumber = 14417807
В плане выполнения вы увидите восклицательный знак, предупреждающий, что в запросе имеется потенциальная проблема. Наведя курсор на оператор SELECT, можно увидеть, что происходит неявное преобразование (CONVERT_IMPLICIT), что может помешать оптимизатору использовать SEEK (поиск).
(1 row affected)
Table ‘Employee’. Scan count 1, logical reads 9, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Вопрос - как исправить это. Это действительно просто, но потребует изменения кода. Давайте вернемся к нашему запросу.
SELECT BusinessEntityID, NationalIDNumber, LoginID, HireDate,JobTitle
FROM HumanResources.Employee
WHERE NationalIDNumber = 14417807
Помните, что мы запрашивали целое значение. Простое добавление кавычек, ограничивающих значение, поможет нам решить проблему. Всегда важно знать, какого типа столбцы, которые вы используете в запросе. В данном примере, поскольку тип NVARCHAR, все, что необходимо сделать, это передать символьное значение. Это выполняется кавычками-ограничителями вокруг значения.
SELECT BusinessEntityID, NationalIDNumber, LoginID, HireDate,JobTitle
FROM HumanResources.Employee
WHERE NationalIDNumber = '14417807'
Просто посмотрим на результаты. Напомним, что выше мы имели число сканирований 1, логических чтений 9, физических чтений 0. Теперь при выполнении получим:
(1 row affected)
Table ‘Employee’. Scan count 0, logical reads 4, physical reads 2, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
На графическом плане также видно, что предупреждение ушло, и мы имеем SEEK вместо SCAN, что значительно эффективней.
Имеется много способов, с помощью которых вы можете решить проблемы, связанные с неявными или явными преобразованиями и дополнительной нагрузкой, которую они создают. В большинстве случаев очень легко поправить ситуацию путем незначительных изменений в коде. Чтобы помочь вам найти их в вашей среде, Jonathan Kehayia написал запрос для нахождения столбцов с неявным преобразованием в кэше планов.
Обратные ссылки
Автор не разрешил комментировать эту запись
Комментарии
Показывать комментарии Как список | Древовидной структурой