очень большие объёмы данных. Данные в хранилище данных обычно
считываются многочисленными запросами, но не изменяются одновременно
многими транзакциями.
Обычно за создание индексов отвечает АБД, но разработчик приложения
может сообщить АБД полезную информацию о том, какие столбцы
являются хорошими кандидатами для индексирования. Дело в том, что вы
можете знать о своем приложении больше, чем АБД (подробнее о вопросах
индексирования и о добавлении индексов см. в главе 10).
Используйте WHERE вместо HAVING
Фраза WHERE используется в качестве фильтра строк; фраза HAVING используется
для фильтрации групп строк. Поскольку HAVING отфильтровывает
группы строк после того, как эти группы будут сформированы (на что также
требуется некоторое время), нужно там, где это возможно, отфильтровывать
строки с помощью фраз WHERE. Таким образом удастся избежать потерь
времени на создание трупп, которые затем будут отброшены.
Следующий плохой запрос отбирает product_type_id и среднюю цену
для товаров с product_type_id 1 или 2. Чтобы сделать это, запрос выполняет
следующие действия:
■ использует фразу GROUP BY для группировки строк в блоки с одинаковыми
значениями product_type_id;
■ использует фразу HAVING для ограничения возвращаемых результатов
теми группами, у которых product_type_id равен 1 или 2 (плохой
вариант, так как должна работать фраза WHERE).
□ — ПЛОХОЙ ВАРИАНТ (вместо WHERE используется HAVING)
SELECT product_type_id, AVG(price)
FROM products
GROUP BY product_type_id
HAVING product_type_id IN (1, 2);
PRODUCT_TYPE_ID AVG(PRICE)
1 24.975
2 26.22
В следующем примере переписывается предыдущий запрос, чтобы в
нем вместо HAVING использовалась фраза WHERE: это позволит с самого начала
оставить только те строки, где product_type_id равен 1 или 2:
П — ХОРОШИЙ ВАРИАНТ (вместо HAVING используется WHERE)
SELECT product_type_id, AVG(price)
FROM products
WHERE product_type_id IN (1, 2)
GROUP BY product_type_id;
604 Глава 16
PRODUCT_TYPE_ID AVG(PRICE)
1 24.975
2 26.22
Используйте UNION ALL вместо UNION
UNION ALL используется для того чтобы получить все строки, отобранные
двумя запросами, включая и повторяющиеся (дублирующие) строки. UNION
используется для получения только неповторяющихся строк, отобранных
двумя запросами. Поскольку при выполнении UNION дублирующиеся строки
отбрасываются (на что требуется некоторое время), рекомендуется,
когда это возможно, выполнять UNION ALL.
Следующий запрос использует UNION (плохой вариант, так как должен
работать UNION ALL) для получения строк из таблиц products и more_
products; возвращаются все неповторяющиеся строки из таблиц products
и more_products:
□ — ПЛОХОЙ ВАРИАНТ (используется UNION, а не UNION ALL)
SELECT prd_id, prd_type_ia, паше
FROM products
UNION
SELECT product_id, product_type_id, name
FROM more_products;
PRODUCT_ID PRODUCT_TYPE_ID NAME
1 1 Modern Science
2 1 Chemistry
3 2 Supernova
3 Supernova
4 2 Lunar Landing
4 2 Tank War
5 2 Submarine
5 2 Z Files
6 2 2412: The Return
7 3 Space Force 9
8 3 From Another Planet
g 4 Classical Music
10 4 Pop 3
11 4 Creative Yell
12 My Front Line
Следующий запрос переписывает предыдущий пример с использованием
UNION ALL. На этот раз возвращаются все строки из таблиц products и
more_products, в том числе и дублирующие друг друга:
□ __ ХОРОШИЙ ВАРИАНТ (используется UNION ALL, а не UNION)
SELECT product_id, product_type_id, name
FROM products
UNION ALL
SELECT prd_id, prd_type_id, name
Настройка высокой производительности SQL 605
FROM more_products;
PRODUCT_ID PRODUCT_TYPE_ID NAME
1 1 Modern Science
2 1 Chemistry
3 2 Supernova
4 2 Tank War
5 2 Z Files
6 2 2412: The Return
7 3 Space Force 9
8 3 From Another Planet
9 4 Classical Music
10 4 Pop 3
11 4 Creative Yell
12 My Front Line
1 1 Modern Science
2 1 Chemistry
3 Supernova
4 _ 2 Lunar Landing
5 2 Submarine
Используйте EXISTS вместо IN
Фраза IN используется для проверки, содержится ли значение в списке.
Фраза EXISTS используется для проверки существования строк, возвращаемых
подзапросом. EXISTS отличается от IN: EXISTS проверяет только сам
факт существования строк, в то время как IN проверяет фактические значения.
Обычно EXISTS обеспечивает лучшую производительность в подзапросах,
чем IN. Поэтому, когда возможно, следует вместо IN использовать
EXISTS.
Вам следует обратиться к разделу главы б “Использование операторов
EXISTS и NOT EXISTS с коррелированными подзапросами” за сведениями о
том, когда вам следует использовать EXISTS с коррелированным подзапросом
(важно помнить, что коррелированные подзапросы могут обрабатывать
значения NULL).
Следующий запрос использует IN (плохой вариант, так как следовало