2016-06-29 3 views
0

У меня возникли некоторые проблемы с производительностью при использовании SQL-запросов с функциями агрегации, поэтому я подумал, что было бы неплохо понять, как именно работает создание индекса. Я наткнулся на одну вещь, которую я не мог понять: в чем разница между этими двумя директивами создания ?:Синтаксис создания индекса Oracle

1.)CREATE INDEX FIELD1_INDEX ON TABLE1 (FIELD1) ONLINE TABLESPACE XXX; 
    CREATE INDEX timeofrequest_INDEX ON TABLE1 (timeofrequest) ONLINE TABLESPACE XXX; 

2.)CREATE INDEX COMBINED_INDEX ON TABLE1 (FIELD1, FIELD2) ONLINE TABLESPACE XXX; 

Причина, почему я спрашиваю, что у меня есть запрос типа:

SELECT SUM(field1) FROM table1 WHERE timeofrequest BETWEEN 1 AND 2; 

В таблице 1 содержится много данных, поэтому для получения этого запроса требуется более 20 секунд. Чтобы избежать продолжительной работы, я попытался перейти с подходом 1 и создать индекс для каждого затронутого поля. Действительно, он все еще слишком медленный. Из анализа плана выполнения я вижу, что используется индекс timeofrequest, но не тот, который используется для field1. Должен ли он помочь, если я создам комбинированный с одним заявлением? Разве это имеет значение?

ответ

0

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

В вашем первом примере у вас есть два индекса против отдельных столбцов. Второй пример - индекс SINGLE с двумя столбцами. Ваш первый пример будет ТОЛЬКО использовать тот или иной, но не оба для любого заданного оператора одиночной выборки (CBO решит, что использовать на основе вашего запроса ...).

Пример:

SELECT SUM(field1) FROM table1 WHERE timeofrequest BETWEEN 1 AND 2; 

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

Пример для второго индекса:

SELECT SUM(field1) FROM table1 WHERE FIELD1 = 'x'; 

Предполагая, что вы не имели INDEX только против «FIELD1», это было бы использовать COMBINED_INDEX у вас есть на месте, и получать все записи в первом поле вашего индекса ,

Если вы имели:

SELECT SUM(field1) FROM table1 WHERE FIELD2 = 'y'; 

Это НЕ будет использовать combined_index, так как индекс построен вокруг первого использования FIELD1, затем FIELD2.

Если вы имели:

SELECT SUM(field1) FROM table1 WHERE FIELD1 = 'x' and FIELD2 = 'y'; 

Это будет по-прежнему использовать COMBINED_INDEX, но здесь вы обеспечить уровень детализации тоньше. Он будет использовать полный индекс (field1 и field2 ...), чтобы возвращать ваши строки намного быстрее. Почему это полезно? Ну, возможно, у вас мог бы быть индекс на FIELD1, и просто поиск на ONLY поле1 все равно принесет много тысяч (или десятков тысяч или миллионов ...) записей, поэтому возможность предоставить другой столбец как часть индекса просто поможет настроить нужные вам записи ... что, в свою очередь, обеспечивает более высокую избирательность.

ВАЖНОЕ примечание! Помните, что CBO определяет наилучший подход. Если у вас плохая мощность (объем таблицы исследований ...) в таблице для этого столбца, возможно, вы даже не можете использовать индекс вообще, и полное сканирование таблицы будет лучше в соответствии с CBO. Если у вас высокая мощность и вы по-прежнему не используете индекс, возможно, вам понадобится проанализировать таблицу и индексы на ней, а затем повторно запустите свой план объяснения, чтобы узнать, получили ли вы новые результаты. Возможно также, что у вас может быть низкая мощность из-за того, что большая часть данных в таблице меняется, а не недавно анализируется. Анализ таблицы/индексов - довольно важная вещь, которую можно легко упустить. В нескольких случаях я нашел экземпляры, где я работал, что просто переанализировал таблицу и/или индексы, сделав невероятные улучшения.

Ознакомьтесь с анализом таблиц и использованием DBMS_STATS.

https://docs.oracle.com/cd/B28359_01/appdev.111/b28419/d_stats.htm

Другое решение также является то, что если у вас есть огромное количество данных, и в столбце «Время запроса» на самом деле имеет только небольшой определенный набор значений (возможно, в вашей таблице 50 миллионов записей есть только 20 различных значений ..), то вы можете выбрать настройку секционированной таблицы и предоставить индексы оттуда. Это значительно улучшит время выполнения запросов.

+0

Большое спасибо, я ценю вашу помощь –

Смежные вопросы