Вопрос

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

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

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

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

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

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

Это было полезно?

Решение

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

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

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

Другие советы

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

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;

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

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

В этом случае добавление НАЧИНАЮЩЕЙ подсказки является Одностороннее движение чтобы вернуть его к исходному плану (т.диск из таблицы А), не диктуя слишком много оптимизатору (т.е.он не заставляет оптимизатора выбирать какие-либо конкретные методы соединения).

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

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

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

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

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

РИ,

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

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

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

Б) Изменение объема данных/структуры данных.

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

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

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

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

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

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

Мэтью

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top