INSERT во временную таблицу GTT очень медленно из PL / SQL

У меня есть запрос, который отлично работает при выполнении из SQL.

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

Я дал еще 2 подсказки, чтобы увидеть, помогут ли они, как видно. Один предназначен для прямого пути APPEND, а другой - для использования существующего индекса BTree на КПК.

Когда этот запрос выполняется для заменяемых переменных из SQL, результаты являются мгновенными, но тот же запрос внутри процедуры занимает 8 секунд или более.

Помимо плана процедуры, которому администратор базы данных еще не выполнил, что делать, если вы думаете о каких-либо вопиющих промахах? Заранее спасибо.

 
     INSERT                                                           /*+ APPEND */
          INTO  tmp_search_gross_docs (document_id,
                                       last_name,
                                       first_name,
                                       person_doc_association_id,
                                       association_date)
       SELECT                 /*+INDEX(pda IDX_DOC_PDOC_DOCID ) USE_NL(pda doc) */
             pda.document_id,
              last_name,
              first_name,
              person_doc_association_id,
              association_date
         FROM   pda,
              (SELECT /*+INDEX_COMBINE(attr IDX_BMP_SEARCH_FN,IDX_BMP_SEARCH_LN)*/
                      document_id, last_name, first_name
                 FROM doc attr
                WHERE first_name LIKE l_first_name OR last_name LIKE l_last_name) doc
        WHERE pda.document_id = doc.document_id;
                         ) doc
                 WHERE pda.document_id = doc.document_id;

  

EXPLAIN Plan (от Toad для связывания переменных)

ВСТАВИТЬ ЗАЯВЛЕНИЕ ALL_ROWSCost: 1 086 010 байтов: 15 309 420 Количество элементов: 364 510
11 ЗАГРУЗИТЬ КАК ВЫБРАТЬ TMP_SEARCH_GROSS_DOCS
10 ДОСТУП К ТАБЛИЦАМ ПО ИНДЕКСУ ROWID TABLE PDA Стоимость: 3 байта: 20 Количество элементов: 1
9 Вложенных циклов Стоимость: 1086 010 байтов 15 309 420 Количество элементов: 364 510
ДОСТУП К 7 ТАБЛИЦАМ ПО ИНДЕКСУ ROWID TABLE ATTR Стоимость: 23 893 байта: 8 019 220 Количество элементов: 364 510
ПРЕОБРАЗОВАНИЕ 6 BITMAP в ROWIDS
5 BITMAP ИЛИ
ОБЪЕДИНЕНИЕ 2 BITMAP
1 ИНДЕКС BITMAP RANGE SCAN INDEX (BITMAP) IDX_BMP_SEARCH_FN 4 BITMAP MERGE
3 BITMAP INDEX RANGE SCAN INDEX (BITMAP) IDX_BMP_SEARCH_LN 8 INDEX RANGE SCAN INDEX IDX_PDA_EXP_DOC Стоимость: 2 Количество элементов: 1

Мощность 364 510 кажется неправильной, поскольку таблица содержит 3738562 строки, а для подставленных значений столбцов в WHERE количество составляет только 8892.

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

Фактический план из PL / SQL все еще недоступен.

Не уверен, добавляет ли это ценную информацию или нет. Но мысль редактировать все равно буду. Спасибо


person user2275460    schedule 12.04.2013    source источник
comment
Что еще вы делаете в этой процедуре?   -  person a_horse_with_no_name    schedule 13.04.2013
comment
Не уверен, что это поможет, но в конечном итоге создается набор записей, который затем считывается приложением. Я должен отметить, что я пробовал BULK COLLECT с коллекцией на том же SQL, и это тоже было с той же производительностью. Как-то кажется, что SELECT не выбирает оптимальный путь, как при выполнении из редактора ..   -  person user2275460    schedule 13.04.2013


Ответы (3)


Во-первых, я не думаю, что вставка в GTT с помощью append имеет какую-то логику. Я могу ошибаться, но из того, что я знаю, append обходит буферный кеш и записывает непосредственно в файл, он записывает выше верхней отметки и не позволяет выполнять запросы до тех пор, пока не будет сделана фиксация. GTT находится не в обычных файлах данных - он во временных файлах и усекается при фиксации (настройки по умолчанию).

Я думаю, что если вам не нужно манипулировать данными после запроса, подумайте о возврате курсора ref в приложение. По сути, это одно и то же - многие слои DAL реализованы таким образом.

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

person haki    schedule 13.04.2013
comment
+1 Вы правы, что скептически относитесь к использованию GTT с append. Преимущество GTT в том, что он всегда должен кэшироваться; обход кеша при первой записи, вероятно, не поможет. Но он все равно может работать, если GTT привязан к сеансу, а не к транзакции. - person Jon Heller; 13.04.2013

Пара вещей, которые вы могли бы изучить.

  1. Не актуально для таблицы GTT. Как вы сказали, создайте таблицу, не вводя дополнительных данных, а при вставке используйте подсказку вставки добавления, чтобы выполнить загрузку прямого пути.

  2. Кроме того, может возникнуть неправильное представление о скорости запроса, если вы видите результаты от Toad. Такие программы, как жаба, автоматически добавляют подсказки для получения первых 50/100/200 строк, поэтому запрос может выполняться быстрее. Вы пробовали перейти к последней записи (значок «>» в ​​сетке) и посмотреть, сколько времени требуется, чтобы получить последнюю строку?

  3. Невозможно настроить запрос или даже написать хороший код, не имея возможности увидеть план. Если это более крупная процедура, вы можете посмотреть на такие вещи, как DBMS_PROFILER. ЕСЛИ вы уверены, что это оператор, вызывающий проблему, вы можете начать с трассировки SQL или объяснить план.

person Rajesh Chamarthi    schedule 12.04.2013
comment
На № 2, да, запрос возвращает 600 нечетных строк для соответствующих параметров, которые я сравниваю с производительностью. Я перешел к последней записи в результатах да. 3. Да, я убедился, что это заявление, вызывающее задержку. План из автономного SQL выглядит хорошо, именно так я настроил и применил его к процедуре. Нет ни прав на запуск Trace, ни фактического плана выполнения процедуры. Тем не менее, спасибо за повторение пунктов. - person user2275460; 12.04.2013

Адаптивное совместное использование курсора не применяется к Предикаты LIKE.

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

Одно из возможных решений - заставить Oracle всегда выполнять жесткий синтаксический анализ вашего запроса. Я использовал это решение, как объяснил Дион Чо в этой ветке OTN:

dbms_stats.set_table_stats('schema','DOC',num_rows=>null,no_invalidate=>false);

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

Кроме того, ваша подсказка INDEX_COMBINE может быть неверной. . Между индексами не должно быть запятой. Однако синтаксис подсказок плохо документирован, и синтаксический анализатор подсказок часто работает «частично». Ваш намек, вероятно, оценивается как эквивалент /*+INDEX_COMBINE(attr)*/, который может работать, а может и не работать так, как вы хотите. Вы никогда не узнаете без планов.

Есть веские причины избегать подсказок, особенно если у вас нет удобного доступа к планам с объяснениями.

person Jon Heller    schedule 15.04.2013
comment
Я подтвердил, что подсказки позволяют использовать индексы, так что синтаксис определенно в порядке. Я все еще пытаюсь изучить ваш другой комментарий о включении жесткого синтаксического анализа. Как это выключить, если вообще? Учитывая, что в этом посте упоминается опасность конфликта библиотечных кешей. - person user2275460; 17.04.2013
comment
Вам, вероятно, не нужно беспокоиться о кеш-памяти библиотеки. Если на выполнение запроса требуется 8 секунд, вероятно, он выполняется не очень часто. Запустите select count(*) from gv$sql; и сравните это с количеством отдельных запросов, которые ваша процедура выдала бы, если бы она всегда выполняла жесткий синтаксический анализ. Кроме того, я все еще скептически отношусь к тому, что подсказки работают. Я думаю, что это тот случай, когда план объяснения, который вы видите, не совпадает с реальным планом выполнения. Я не уверен, почему у вас проблемы с получением реального плана, его должно быть легко получить. - person Jon Heller; 17.04.2013