8.2.2.4 Оптимизация производных таблиц и ссылок на представления с помощью слияния или материализации
Оптимизатор может обрабатывать ссылки на производные таблицы, используя два подхода (которые также применимы к ссылкам на представления):
Слить производную таблицу в основной блок запроса
Материализовать производную таблицу в внутреннюю временную таблицу
Пример 1:
SELECT * FROM (SELECT * FROM t1) AS derived_t1;
При слиянии производной таблицы derived_t1, запрос выполняется аналогично:
SELECT * FROM t1;
Пример 2:
SELECT *
FROM t1 JOIN (SELECT t2.f1 FROM t2) AS derived_t2 ON t1.f2=derived_t2.f1
WHERE t1.f1 > 0;
При слиянии производной таблицы derived_t2, запрос выполняется аналогично:
SELECT t1.*, t2.f1
FROM t1 JOIN t2 ON t1.f2=t2.f1
WHERE t1.f1 > 0;
При материализации, derived_t1 и derived_t2 рассматриваются как отдельные таблицы в своих соответствующих запросах.
Оптимизатор обрабатывает производные таблицы и ссылки на представления одинаково: он избегает ненужной материализации всякий раз, когда это возможно, что позволяет продвигать условия из основного запроса в производные таблицы и создавать более эффективные планы выполнения. (См. Раздел 8.2.2.2, «Оптимизация подзапросов с материализацией».)
Если слияние приведет к основному блоку запроса, который ссылается на более чем 61 базу таблиц, оптимизатор выбирает материализацию вместо этого.
Оптимизатор распространяет предложение ORDER BY в производной таблице или ссылке на представление на основной блок запроса, если все эти условия выполняются:
Основной запрос не сгруппирован и не агрегирован.
Основной запрос не указывает
DISTINCT,HAVINGилиORDER BY.Основной запрос имеет эту производную таблицу или ссылку на представление как единственный источник в предложении
FROM.
В противном случае оптимизатор игнорирует предложение ORDER
BY.
Доступны следующие способы влияния на то, пытается ли оптимизатор слить производные таблицы и ссылки на представления в основной блок запроса:
-
Флаг
derived_mergeсистемной переменнойoptimizer_switchможет быть использован, предполагая, что другие правила не препятствуют слиянию. См. Раздел 8.9.2, «Переключаемые оптимизации». По умолчанию, флаг включен для разрешения слияния. Отключение флага предотвращает слияние и избегает ошибок.Флаг
derived_mergeтакже относится к представлениям, не содержащим предложенияALGORITHM. Таким образом, если возникает ошибка для ссылки на представление, использующей выражение, эквивалентное подзапросу, добавлениеALGORITHM=TEMPTABLEв определение представления предотвращает слияние и имеет приоритет над значениемderived_merge. -
Можно отключить слияние, используя в подзапросе любые конструкции, которые препятствуют слиянию, хотя они не так явны в своем влиянии на материализацию. Конструкции, которые препятствуют слиянию, одинаковы для производных таблиц и ссылок на представления:
Флаг derived_merge также относится к представлениям, не содержащим предложения ALGORITHM. Таким образом, если возникает ошибка для ссылки на представление, использующей выражение, эквивалентное подзапросу, добавление ALGORITHM=TEMPTABLE в определение представления предотвращает слияние и имеет приоритет над текущим значением derived_merge.
Если оптимизатор выбирает стратегию материализации вместо слияния для производной таблицы, он обрабатывает запрос следующим образом:
Оптимизатор откладывает материализацию производной таблицы до тех пор, пока ее содержимое не потребуется во время выполнения запроса. Это улучшает производительность, потому что отложенная материализация может привести к тому, что ее вообще не придется выполнять. Рассмотрим запрос, который объединяет результат производной таблицы с другой таблицей: если оптимизатор сначала обработает другую таблицу и обнаружит, что она возвращает 0 строк, объединение не нужно выполнять дальше, и оптимизатор может полностью пропустить материализацию производной таблицы.
Во время выполнения запроса оптимизатор может добавить индекс к производной таблице, чтобы ускорить получение строк из нее.
Рассмотрим следующее предложение EXPLAIN для запроса SELECT, который содержит производную таблицу:
EXPLAIN SELECT * FROM (SELECT * FROM t1) AS derived_t1;
Оптимизатор избегает материализации производной таблицы, откладывая ее до тех пор, пока результат не потребуется во время выполнения SELECT. В этом случае запрос не выполняется (потому что он выполняется в предложении EXPLAIN), поэтому результат никогда не нужен.
Даже для запросов, которые выполняются, отложенная материализация производной таблицы может позволить оптимизатору полностью избежать материализации. В этом случае выполнение запроса быстрее на время, необходимое для выполнения материализации. Рассмотрим следующий запрос, который объединяет результат производной таблицы с другой таблицей:
SELECT *
FROM t1 JOIN (SELECT t2.f1 FROM t2) AS derived_t2
ON t1.f2=derived_t2.f1
WHERE t1.f1 > 0;
Если оптимизация обрабатывает t1 сначала, и предложение WHERE создает пустой результат, объединение обязательно будет пустым, и производная таблица не должна материализовываться.
В случаях, когда для производной таблицы требуется материализация, оптимизатор может добавить индекс к материализованной таблице для ускорения доступа к ней. Если такой индекс позволяет использовать доступ ref к таблице, он может значительно сократить количество считываемых данных во время выполнения запроса. Рассмотрим следующий запрос:
SELECT *
FROM t1 JOIN (SELECT DISTINCT f1 FROM t2) AS derived_t2
ON t1.f1=derived_t2.f1;
Оптимизатор создает индекс по столбцу f1 из derived_t2, если это позволит использовать доступ ref для плана выполнения с наименьшей стоимостью. После добавления индекса оптимизатор может рассматривать материализованную производную таблицу так же, как обычную таблицу с индексом, и он аналогично выигрывает от сгенерированного индекса. Накладные расходы на создание индекса незначительны по сравнению со стоимостью выполнения запроса без индекса. Если доступ ref приведет к более высокой стоимости, чем какой-либо другой метод доступа, оптимизатор не создает индекс и не теряет ничего.
Для вывода следа оптимизатора, слитая производная таблица или ссылка на представление не отображаются как узел. В плане верхнего запроса отображаются только его основанные таблицы.
© 2025 Oracle
Licensed under the GPLv2 License.