Методы оптимизации запросов к SQL Server - Советы для написания эффективных и быстрых запросов
Navita Kumari
Инновационный центр - Группа организаций Baba Farid
Автор перевода: Прищепа В.В.
Аннотация - SQL можно использовать для извлечения данных из любых баз данных. Чтобы получить один и тот же результат, можно написать различные SQL запросы. Для наилучшей производительности необходимо использовать лучшие, наиболее быстрее и эффективные запросы. Так что необходимо конфигурировать запросы на основании требований пользователей и решаемых задач. Эта статья раскрывает каким же образом SQL запросы могут быть оптимизированы для лучшей производительности. Оптимизация запросов тема очень глубокая, но мы будем стараться охватить наиболее важные моменты. В этой статье мы не будем сосредотачиваться на глубоком анализе базы данных, а обсудим простые советы по настройке запросов и приемы, которые могут быть применены, чтобы получить немедленный выигрыш в производительности.
I. ВВЕДЕНИЕ
Лучший способ оптимизации производительности состоит в том, чтобы попытаться написать свои запросы используя различные способы и приемы, и сравнить их планы выполнения. Здесь представлены различные методы, которые можно использовать, чтобы попытаться оптимизировать запросы к базе данных. Оптимизация запросов является важным навыком для разработчиков SQL и администраторов баз данных. В целях повышения производительности запросов SQL, разработчики и администраторы баз данных должны понимать работу оптимизатора запросов и методы, которые он использует, чтобы выбрать путь доступа и подготовить план выполнения запроса. Настройка запросов включает в себя знание методов оптимизаторов основанных на подсчете затрат и эвристических методов, также необходимо знание инструментов SQL-платформы, обеспечивающих просмотр плана выполнения запроса.
II. ОБЗОР ВЫПОЛНЕНИЯ ЗАПРОСОВ С ИСПОЛЬЗОВАНИЕМ СТАТИСТИКИ ЧТЕНИЯ/ЗАПИСИ
Важным параметром является количество логических операций чтения производящихся по запросу. Возможность просматривать этот параметр предусмотрена в SQL Server Management Studio. Для определения числа логических операций чтения, вы можете включить или выключить отображение параметра STATISTICS IO с помощью такого запроса:
SET STATISTICS IO ON
Рассмотрим следующий запрос:
SELECT * FROM tablename
В окне результата SQL Server Management Studio вернулось следующее сообщение: "Table ‘tablename’. Scan count 1, logical reads 33, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0".
При оптимизации запросов необходимо анализировать количество операций логического чтения, потому что оно будет оставаться постоянным, когда запускается тот же запрос. На другие виды чтения воздействуют внешние факторы, которые могут влиять на время выполнения запросов. При настройке запросов SQL, наша цель должна состоять в том, чтобы получить число логических операций чтения как можно более низкой. Чем меньше логических операций чтения, тем меньше время выполнения запроса.
III. ОБЩИЕ РЕКОМЕНДАЦИИ ПО ОПТИМИЗАЦИИ ЗАПРОСОВ
Используйте конкретные имена столбцов вместо * в запросе SELECT
Запрос SQL, становится быстрее, если использовать имена столбцов в SELECT вместо '*'. Так что нам нужно ограничить запросы с выборкой всех столбцов, выбрав только определенные столбцы из таблицы. Это приводит к выигрышу общей производительности, уменьшению сетевого трафика.
Пример:
SELECT col_1, col_2, col_3, col_4, subject FROM table_name;
вместо:
SELECT * FROM table_name.
Используйте альтернативные методы для возврата общего количества строк таблицы вместо COUNT (*)
SELECT COUNT (*) делает полное сканирование таблицы, это может занять много времени для больших таблиц. Если нам нужно узнать количество строк таблицы, мы можем использовать альтернативный способ – системную таблицу sysindexes. В ней присутствует столбец ROWS, содержащий общее количество строк для каждой таблицы в системе. Таким образом, мы можем использовать следующий оператор выбора:
SELECT rows FROM sysindexes
WHERE id = OBJECT_ID ('table_name') AND indid < 2.
Старайтесь избегать предложения HAVING в операторе SELECT
Его можно использовать, как фильтр в маленьких выборках строк.
Пишите:
SELECT Col_1, count (Col_1) FROM table_name
WHERE col_1!= 'testvalue1' AND col_1!= 'testvalue1'
GROUP BY col_1;
вместо:
SELECT Col_1, count (Col_1) FROM table_name
GROUP BY Col_1
HAVING Col_1!= ‗testvalue1‘ AND Col_1!= 'testvalue2'.
Постарайтесь свести к минимуму количество подзапросов
Пишите:
SELECT col_1 FROM table_name1
WHERE (col_2, col_3) = (SELECT MAX (col_2), MAX (col_3) FROM table_name2)
AND col_4 = 'testvalue1';
вместо:
SELECT col_1 FROM table_name1
WHERE col_2 = (SELECT MAX (col_2) FROM table_name2)
AND col_3 = (SELECT MAX (col_3) FROM table_name2)
AND col_4 = 'testvalue1'.
Используйте операторы EXISTS и IN с осторожностью и правильно:
Обычно IN имеет самую низкую производительность, он является эффективным только тогда, когда большинство критериев фильтрации помещаются в подзапрос.
EXISTS эффективен, когда большинство критериев фильтрации находятся главном запросе.
Например:
SELECT * FROM table1 t1
WHERE EXISTS (SELECT * FROM table2 t2 WHERE t2.col_id = t1.col_id);
вместо:
SELECT * FROM table1 t1
WHERE t1.col_id IN (SELECT t2.col_id FROM table2 t2).
Используйте EXISTS вместо DISTINCT при запросе с объединением таблиц, которые имеют отношения один-ко-многим
Например:
SELECT d.col_id, d.col2 FROM table1 d
WHERE EXISTS (SELECT 'X' FROM table2 e WHERE e.col2 = d.col2);
вместо:
SELECT DISTINCT d.col_id, d.col2 FROM table1 d, table2 e
WHERE e.col2 = e.col2.
Попробуйте использовать UNION ALL вместо UNION, если это возможно
UNION ALL работает быстрее, чем UNION, так как UNION ALL не считает дубликаты. Инструкция UNION проверяет таблицу на наличие дубликатов строк даже если они отсутствуют.
Пример:
SELECT id, col1 FROM table1
UNION ALL SELECT id, col1 FROM table2;
вместо:
SELECT id, col1, col2 FROM table1
UNION SELECT id, col1 FROM table2.
Тщательно подбирайте условия в инструкции WHERE
Например, для сравнения чисел пишите:
SELECT id, col1, col2 FROM table
WHERE col2 > 10;
вместо:
SELECT id, col1, col2 FROM table
WHERE col2 != 10.
Для сравнения строк:
SELECT id, col1, col2 FROM table
WHERE col1 LIKE 'Nav%';
вместо:
SELECT id, col1, col2 FROM table
WHERE SUBSTR(col1,1,3) = 'Nav'.
Для сравнения чисел в диапазоне:
SELECT Col1, Col2 FROM table
WHERE Col3 BETWEEN MAX (Col3) and MIN (Col3);
вместо:
SELECT Col1, Col2 FROM table
WHERE Col3 >= MAX (Col3) and Col3 <= MIN (Col3).
Применяйте модифицированное значение колонки в инструкции WHERE только при необходимости.
Пример:
SELECT id, Col1, Col2 FROM table
WHERE Col2 < 25000;
вместо:
SELECT id, Col1, Col2 FROM table
WHERE Col2 + 10000 < 35000.
IV. ЕЩЕ НЕСКОЛЬКО СОВЕТОВ ПО ОПТИМИЗАЦИИ ЗАПРОСОВ/ТАБЛИЦ/ХРАНИМЫХ ПРОЦЕДУР
V. ВЫВОДЫ
Оптимизация запросов имеет очень большое влияние на производительность СУБД и постоянно развивается с новыми, более сложными стратегиями оптимизации. Оптимизация запросов является общей задачей администраторов баз данных и разработчиков приложений для того, чтобы оптимизировать общую производительность системы баз данных. Даже если у вас есть мощная инфраструктура, производительность может быть существенно понижена неэффективными запросами.
Необходимо стараться следовать общим советам, которые упоминались выше, чтобы получить наилучшую производительность запросов. Возможно достижение наилучшей производительности, если превратить эти советы в правила. Методы, описанные в этой статье, позволяют произвести базовую оптимизацию запросов, таблиц, индексов и хранимых процедур в целях повышения производительности. Основной акцент был сделан на оптимизации запросов.
ССЫЛКИ