2009-06-15 2 views
1

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

Есть ли «лучшая практика» для создания таких запросов? Например. Используйте строки для построения динамического запроса, используйте огромный список команд IF THEN .. ELSE и т. Д.? Может ли кто-нибудь представить простой пример или указать мне какую-нибудь литературу, которая поможет? Вот несколько psuedocode для хранимой процедуры, которую я разрабатываю, которая принимает набор параметров и курсор ref.

v_query = "SELECT ....."; 
v_name = ... -- retrieve "name" parameter from collection 
if v_name is not null then 
    v_query := v_query || ' AND table.Name = ' || v_name; 
end if; 
open search_cursor for v_query; 
... 

* Под «динамическим набором параметров поиска» подразумевается, что я передаю набор параметров. Я полагал, что это будет проще, чем заставить вызывающего абонента пройти по 20 параметрам, если они хотят только поискать на нем.

+0

Что значит «проблема оптимизации процедуры»? Выполняют ли ваши запросы плохо, или вы стремитесь к удобочитаемости, или ...? – DCookie

+0

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

ответ

4

Существуют проблемы с использованием подхода статического запроса; также будьте очень осторожны в использовании опции CURSOR_SHARING = FORCE - она ​​может действительно поднять ад с вашей системой, если вы еще не сделали тест покрытия, чтобы все ваши другие запросы работали так, как вы хотите.

Проблема с статическими запросами:

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

  2. Наличие одного статического оператора с переменными подстановки предотвратит оптимизатор от интеллектуального выбора того, какой индекс использовать на основе распределения данных. В динамическом запросе (или в первом запуске запроса с переменными привязки) Oracle увидит, насколько избирательным является ваше ограничение; очень избирательное ограничение станет основным кандидатом на использование индекса. Например, если ваша таблица имела строку для каждого человека в США, STATE = 'Аляска' будет гораздо чаще использовать индекс в STATE, чем STATE = 'California'.

Конечно, в обоих этих случаях, если динамические столбцы в ИНЕКЕ не индексируются в любом случае, это не имеет значения, хотя я был бы удивлен, если бы это было так, в базе данных размером ты говоришь о.

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

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

Одна вещь, которую следует учитывать: если эта система является в основном автономной (другими словами, не постоянно обновляемая или вставленная в - заполненная периодическими нагрузками объемных данных), вы можете посмотреть на использование индексов BITMAP. Индексы битмапа отличаются от обычных индексов b-дерева тем, что несколько индексов в одной таблице могут использоваться одновременно, а индексы растровых изображений намного меньше на диске, чем b-деревья. Они очень хорошо работают для таких приложений, где у вас будет множество ограничений, которые не могут быть определены во время разработки. Вам нужно только поместить индексы растрового изображения в столбцы с относительно небольшим количеством значений - например, одно значение составляет не менее 1/1000 таблицы, поэтому не используйте растровые изображения для уникальных столбцов.

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

+0

Спасибо за понимание! Они очень полезны. –

1

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

Решение представляет собой отдельный пакет для каждой таблицы, в соответствии с критериями поиска и построения SQL для запуска поиска. Мы воспользовались старой системой, которую заменяли, чтобы узнать, какие наиболее распространенные типы запросов были выполнены пользователями, и удостоверились, что эти поисковые запросы были лучшими, путем настройки создаваемых запросов (поддерживаемых стратегическим использованием индексов). Поскольку каждый пакет отвечал только за запросы к одной таблице, он мог иметь специальный код, предназначенный для работы с этой таблицей (включая нечетный намек, в нескольких редких случаях).

Один вопрос/проблема, которую вам нужно решить, жестко задает критерии (например, WHERE SURNAME='SMITH') или использует переменные связывания? Использование переменных привязки уменьшает жесткий синтаксический анализ, что снижает нагрузку на сервер базы данных; однако при использовании SQL динамически генерируется нецелесообразно использовать переменные связывания. То, как мы закончили, состояло в том, чтобы установить CURSOR_SHARING=FORCE (у которого есть свои недостатки), что было разумным компромиссом в нашем случае.

2

За исключением очень особых случаях, я не думаю, что это желательно (или даже возможно), чтобы попытаться создать оптимизированный запрос. Мой совет - не использовать динамический SQL, если вы можете: трудно читать, трудно отлаживать, трудно оптимизировать, трудно поддерживать.

Сначала напишите общий запрос, который будет работать с любым параметром, отправленным вашей процедуре. По вашему примеру, что бы дать что-то вроде:

SELECT * FROM table WHERE ((v_name IS NULL) OR (table.Name=v_name)); 

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

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

IF particular_set 
THEN 
    /* Specific query */ 
ELSE 
    /* Generic query */ 
END IF; 

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

+1

+1 Это тот же подход, который я использую, я предпочитаю разработку одного оператора STATIC sql, который принимает параметры, используя значение NULL для параметра, для которого предикат оценивает значение true. Преимущество в том, что у меня есть ОДИН оператор, который мне нужно проверить, и ОДИН оператор в общем пуле, а не целое стадо вариаций, чтобы попытаться настроить. Следующий шаг, как указывает Mac, заключается в том, чтобы отбросить «популярные» случаи и иметь эти статические свойства. Это не серебряная пуля, но это подход с VALID. – spencer7593

+0

+1, хороший подход к сложной проблеме. Это удобно для читателя. – DCookie

+1

В моем опыте есть пара проблем с этим подходом. См. Мой комментарий ниже (слишком долго, чтобы соответствовать здесь). –