Общие правила (советы) написания запросов на SQL
Несмотря на то, что все реляционные СУБД имеют встроенный оптимизатор, существуют общие правила, которым стоит придерживаться при создании запросов:
1) Никогда не следует выполнять вычислений на индексированном столбце, например WHERE Amt*5 > : Value
2) Для отключения индекса следует использовать выражения: CName||”, CNum+0 или использовать функцию от значения столбца.
3) Вместо оператора OR предпочтительно использовать оператор UNION.
4) Вместо ключевых слов NOT IN лучше использовать оператор NOT EXISTS.
5) Нельзя допускать значение NULL в индексированном столбце.
6) Не следует использовать оператор LIKE, если достаточно оператора =.
7) Не следует использовать подзапросы, если можно обойтись соединением таблиц JOIN.
8) При объединении таблиц в разделе FROM запроса их следует указывать в порядке уменьшения числа выбираемых из них строк (для продукционного оптимизатора).
9) При ссылке на столбцы при объединении таблиц используйте псевдонимы таблиц.
10) Наибольшее ограничение на выборку строк в разделе WHERE должно стоять первым, если условие выборки включает оператор OR и последним, если содержит только операторы AND (для продукционного оптимизатора).
11) Алгоритмы соединения на основе индексирования производительнее, если меньшую таблицы указать левой. Она загружается в буфер оперативной памяти, а правая затем поблочно считывается для проверки соединения.
12) Используйте полный просмотр, если запрос возвращает более 20% строк из таблиц.
13) В СУБД Oracle8 можно использовать с помощью подсказки /*+INDEX_EFS*/ индексный полный просмотр (EFS), если индекс содержит все столбцы, требуемые в запросе
Простые запросы могут быть написаны самыми различными способами.
Рассмотрим запрос, возвращающий имена всех покупателей, сделавших заказы 10 марта 1990 года.
Варианты реализации запросов:
1) Запрос с объединением таблиц
SELECT DISTINCT CName FROM Customer INNER JOIN Orders ON Orders.CNum=Customer.CNum WHERE Odate=10/03/1990
2) Запрос с коррелируемым подзапросом
SELECT DISTINCT CName FROM Customer WHERE 0<(SELECT COUNT(*) FROM Orders WHERE Odate=10/03/1990 AND Orders.CNum=Customer.CNum)
3) Примечания
Две редакции запроса возвращают аналогичные результаты, однако, время выборки возрастает от первого запроса к второму. Надеяться, что оптимизатор все исправит, не приходится, поэтому важно изначально создавать «правильные» редакции запросов.