Oracle, ВЕДУЩАЯ подсказку — почему это требуется?

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

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

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

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

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

Я задаюсь вопросом, что могло бы заставить Oracle обращаться к этому неправильный путь? Действительно ли это - индексная проблема? Что я должен искать?

5
задан Peter Lang 23 February 2010 в 21:13
поделиться

5 ответов

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

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

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

5
ответ дан 13 December 2019 в 05:34
поделиться

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

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

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

2
ответ дан 13 December 2019 в 05:34
поделиться

Хотя я рекомендую вам использовать Mutex и выяснить, является ли проблема вашим кодом сама по себе, одной из очень сложных и хрупких альтернатив может быть использование «файлов блокировки».

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

Как я уже сказал, он очень сложный и хрупкий, но он не использует Mutex.

Либо используйте Mutex.

-121--3926263-

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

Возвращаясь к мьютексу на мгновение, это просто «объект» ОС для желания лучшего термина. Вам действительно нужны такие устройства на каждой используемой вами ОС. Я уверен, что другие .net clr позволят вам получить доступ и к этим системным примитивам. Я бы просто завернул каждый, используя определенную сборку, которая может быть разной на каждой платформе.

Надеюсь, это имеет смысл.

-121--3926264-

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

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

1
ответ дан 13 December 2019 в 05:34
поделиться

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

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 (если индекс в таблице E.ID5 более избирательный).

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

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

3
ответ дан 13 December 2019 в 05:34
поделиться

RI,

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

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

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

B) Объем данных / изменение структуры данных.

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

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

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

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

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

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

Matthew

1
ответ дан 13 December 2019 в 05:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: