Подсказка Oracle LEADING - зачем это нужно? - PullRequest
5 голосов
/ 24 февраля 2010

Внезапно (но, к сожалению, я не знаю, когда было «внезапно»; я знаю, что в какой-то момент в прошлом он работал нормально) один из моих запросов начал выполнять 7+ секунд вместо миллисекунд. У меня есть 1 локальная таблица и 3 таблицы доступны через ссылку на БД. 3 удаленные таблицы объединены, и одна из них соединена с моей локальной таблицей.

Само предложение локальной таблицы занимает всего несколько миллисекунд для самостоятельного выполнения и возвращает только несколько (максимум 10 или 100) записей. Эти 3 удаленные таблицы содержат много сотен тысяч, возможно, миллионов записей между ними, и если я присоединюсь к ним соответствующим образом, я получу десятки или сотни тысяч записей.

Я присоединяюсь только к удаленным таблицам, чтобы можно было извлечь несколько фрагментов данных, относящихся к каждой записи в моей локальной таблице.

Однако, похоже, происходит то, что Oracle сначала соединяет удаленные таблицы, а затем мою локальную таблицу с этим беспорядком. Это всегда будет плохой идеей, особенно если учесть, что набор данных существует прямо сейчас, поэтому я добавил подсказку /*+ LEADING(local_tab remote_tab_1) */ в свой запрос, и теперь он возвращается в миллисекундах.

Я сравнил планы объяснения, и они почти идентичны, за исключением одного BUFFER SORT на одной из удаленных таблиц.

Мне интересно, что может заставить Оракула подойти к этому неправильно? Это проблема индекса? Что я должен искать?

Ответы [ 5 ]

5 голосов
/ 24 февраля 2010

При выборе плана исполнения оракул оценивает затраты для разных планов. Одна важная информация для этой оценки - количество строк, которые будут возвращены с шага плана выполнения. Oracle пытается оценить тех, кто использует «статистику», то есть информацию о том, сколько строк содержит таблица, сколько различных значений содержит столбец; Насколько равномерно распределены эти значения.

Эти статистические данные являются статистическими данными, и они могут быть неверными, что является одной из наиболее важных причин неправильных оценок оптимизатора оракула.

Так что сбор новой статистики, как описано в комментарии, может помочь. Посмотрите документацию по этому пакету dbms_stats. Есть много разных способов вызова этого пакета.

3 голосов
/ 24 февраля 2010

Распространенная проблема, с которой я столкнулся, - это запрос, объединяющий множество таблиц, где объединения образуют цепочку от одного конца к другому, например ::100100

SELECT *
FROM   tableA, tableB, tableC, tableD, tableE
WHERE  tableA.ID0 = :bind1
AND    tableA.ID1 = tableB.ID1
AND    tableB.ID2 = tableC.ID2
AND    tableC.ID3 = tableD.ID3
AND    tableD.ID4 = tableE.ID4
AND    tableE.ID5 = :bind2;

Обратите внимание на то, как оптимизатор может выбрать вывод запроса из таблицы A (например, если индекс для ID0 хорошо избирателен) или из таблицы E (если индекс для tableE.ID5 более избирателен).

Статистика в таблицах может привести к тому, что выбор между этими двумя планами окажется на острие ножа; в один прекрасный день все работает нормально (вождение из таблицы A), на следующий день собирается новая статистика, и внезапно альтернативный план вождения из таблицы E становится дешевле и выбирается.

В этом случае добавление подсказки LEADING будет в одну сторону , чтобы вернуть его к первоначальному плану (т. Е. Из таблицы А), не навязывая оптимизатору слишком много (т. Е. Он не заставляет оптимизатор выбрать любой конкретный метод соединения).

2 голосов
/ 24 февраля 2010

Вы делаете оптимизацию распределенных запросов, и это хитрый зверь. Возможно, статистика вашей таблицы актуальна, но теперь таблицы в удаленной системе вышли из строя или изменились. Или удаленная система добавила / удалила / изменила индексы, и это нарушило ваш план. (Это отличная причина для репликации, так что вы можете контролировать индексы и статистику по ней.)

Тем не менее, оценка мощности Oracle является основным фактором в плане выполнения. Анализ трассировки 10053 (книга Джонатана Льюиса «Основы затрат на основе Oracle» содержит замечательные примеры от 8i до 10.1) может помочь пролить свет на то, почему ваше утверждение теперь неверно и как подсказка LEADING исправляет его.

Подсказка DRIVING_SITE может быть лучшим выбором, если вы знаете, что всегда хотите, чтобы локальные таблицы сначала объединялись перед тем, как идти после удаленного сайта; оно проясняет ваше намерение, не приводя план, как подсказка LEADING.

1 голос
/ 25 февраля 2010

RI

Трудно быть уверенным в причине проблем с производительностью, не видя SQL.

Когда запрос Oracle работал хорошо раньше и неожиданно начинает работать плохо, это обычно связано с одной из двух проблем:

А) Статистика устарела. Это самая простая и быстрая вещь, которую нужно проверить, даже если у вас есть пакетный процесс, который должен позаботиться об этом ... всегда перепроверяйте.

B) Объем данных / изменение шаблона данных.

В вашем случае выполнение распределенного запроса по нескольким базам данных затрудняет управление производительностью между ними в 10 раз. Можно ли поместить эти таблицы в одну базу данных, возможно, в одну базу данных добавить владельцев схемы?

Подсказки общеизвестно хрупки, так как Oracle не обязан следовать подсказке. Когда объем данных или шаблон изменяется еще больше, Oracle может просто игнорировать подсказку и делать то, что считает лучшим (т.е. худшим; -).

Если вы не можете поместить все эти таблицы в одну базу данных, то я рекомендую вам разбить ваш запрос на два оператора:

  1. INSERT в sub-SELECT для копирования внешних данных в глобальную временную таблицу в вашей текущей базе данных.
  2. ВЫБРАТЬ из глобальной временной таблицы для объединения с другой таблицей.

Вы будете иметь полный контроль над выполнением шага 1 выше, не прибегая к подсказкам. Этот подход, как правило, хорошо масштабируется, если вам потребуется время для настройки производительности. Я видел, как этот подход решает многие сложные проблемы производительности.

Затраты Oracle на создание новой таблицы или вставку кучи записей намного меньше, чем ожидают большинство людей. Определение глобальной временной таблицы дополнительно уменьшает эти накладные расходы.

Мэтью

1 голос
/ 25 февраля 2010

Может быть неуместно, но однажды у меня была похожая ситуация, когда удаленную таблицу заменили на просмотр одной таблицы Когда это была таблица, оптимизатор распределенных запросов «видел», что у него есть индекс. Когда он стал представлением, он больше не мог видеть индекс и не мог стоить план, который использовал индекс для удаленного объекта.

Это было несколько лет назад. Я задокументировал свой анализ в то время здесь .

...