Как я могу выбрать разные подсказки для разных объединений для одной таблицы в подсказке запроса?
-
22-09-2019 - |
Вопрос
Предположим, у меня есть следующий запрос:
select * from A, B, C, D
where A.x = B.x
and B.y = C.y
and A.z = D.z
У меня есть индексы на A.x и B.x, B.y и C.y и D.z
На A.z нет индекса.
Как я могу дать подсказку этому запросу, чтобы использовать подсказку INDEX в A.x, но подсказку USE_HASH в A.z?Похоже, что подсказки принимают только имя таблицы, а не конкретное объединение, поэтому при использовании одной таблицы с несколькими объединениями я могу указать только одну стратегию для всех них.
Альтернативно, предположим, что я использую ВЕДУЩУЮ или УПОРЯДОЧЕННУЮ подсказку по приведенному выше запросу.Обе эти подсказки также принимают только имя таблицы, так как я могу гарантировать, что объединение A.x = B.x выполняется перед соединением A.z = D.z?Я понимаю, что в этом случае я мог бы сначала перечислить D, но представьте, что D впоследствии присоединяется к E и что соединение D-E является последним, которое я хочу получить во всем запросе.
Третья конфигурация - предположим, я хочу, чтобы соединение A.x было первым из всего запроса, и я хочу, чтобы соединение A.z было последним.Как я могу использовать подсказку, чтобы выполнить одно соединение из A, за которым следует соединение B-C, и последним соединение A-D?
Решение
Прежде всего, использование таких подсказок должно быть последним средством, а не обычным способом написания запросов.Большую часть времени вы должны просто следить за тем, чтобы статистика оптимизатора была актуальной, и позволять CBO самому определять оптимальный путь - это его работа!
Подсказка INDEX может указать имя индекса, который вы хотите использовать, следующим образом:
SELECT /*+ INDEX (A, A_X_IDX) */ *
...
(предполагая, что индекс в A.X называется A_X_IDX).
Вы не можете сказать Oracle use использовать индекс в A.X и используйте хэш-соединение с таблицей A в том же операторе, это не имеет смысла.Однако вы можете (если необходимо) указать путь доступа для каждой таблицы примерно так:
SELECT /*+ INDEX (A, A_X_IDX) INDEX(B, B_Y_IDX) USE_HASH(C) */ *
Но, повторяю, это должно быть Редкий чтобы нужно было это сделать.Oracle вложила миллионы долларов и человеко-часы в разработку CBO, так зачем же ее эффективно отключать?
Другие советы
На SQL Server вы бы выполнили хэш-совместную подсказку следующим образом
SELECT * FROM table1 t1
INNER hash join table2 t2 ON t1.id = t2.id
и вы также можете предоставить подсказку по индексу
select * from table1 t1
inner join table2 t2 with (index( bla)) on t1.id = t2.id
Не знаю, как выглядит синтаксис в Oracle, кстати, почему вы используете объединения в старом стиле?Ты все еще на 8i?