Выбрать главу

очень большие объёмы данных. Данные в хранилище данных обычно

считываются многочисленными запросами, но не изменяются одновременно

многими транзакциями.

Обычно за создание индексов отвечает АБД, но разработчик приложения

может сообщить АБД полезную информацию о том, какие столбцы

являются хорошими кандидатами для индексирования. Дело в том, что вы

можете знать о своем приложении больше, чем АБД (подробнее о вопросах

индексирования и о добавлении индексов см. в главе 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 (плохой вариант, так как следовало