как индексировать по столбцу для не является нулевым запросом в Oracle? - PullRequest
0 голосов
/ 09 февраля 2012

У меня есть таблица с большим количеством столбцов, и мой запрос выглядит так

select  * from ( select my_table_id from my_table where start_time_local>=? 
and type_pk<>? and rule_pk=? and this_.name is not null order by start_time_gmt 
desc ) where rownum <= ?

Если я создаю индекс для

(start_time_local, type_pk, rule_pk, name) 

это будет неэффективно, потому что имя varchar (1024). Есть ли лучший способ индексировать что-то вроде:

 (start_time_local, type_pk, rule_pk, isNotNull(name))

Спасибо

Ответы [ 2 ]

2 голосов
/ 09 февраля 2012

Если в поле будет выполняться поиск только для NOT NULL, а не для фактического значения, вы можете использовать индекс на основе функций, чтобы сэкономить место в индексе (и потенциально повысить производительность за счет лучшего использования кэша) ). Например:

CREATE TABLE THE_TABLE (
    ID INT PRIMARY KEY,
    THE_FIELD VARCHAR2(20)
);

CREATE INDEX THE_TABLE_IE1 ON THE_TABLE(NVL2(THE_FIELD, 'Y', 'N')) COMPRESS;

(В индексе будет много повторяющихся значений 'Y' и 'N', поэтому может стоить COMPRESS индекса, как показано выше.)

А затем выберите вот так:

SELECT * FROM THE_TABLE WHERE NVL2(THE_FIELD, 'Y', 'N') = 'Y' -- Equivalent to THE_FIELD IS NOT NULL
SELECT * FROM THE_TABLE WHERE NVL2(THE_FIELD, 'Y', 'N') = 'N' -- Equivalent to THE_FIELD IS NULL

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

CREATE INDEX THE_TABLE_IE1 ON THE_TABLE(NVL2(THE_FIELD, 'Y', NULL)) COMPRESS;
SELECT ID FROM THE_TABLE WHERE NVL2(THE_FIELD, 'Y', NULL) = 'Y' -- Equivalent to THE_FIELD IS NOT NULL

Oracle не индексирует NULL (в индексах на основе B-дерева), поэтому NVL2 (THE_FIELD, 'Y', NULL ) полностью исключит THE_FIELD IS NULL строк из индекса.

2 голосов
/ 09 февраля 2012

Как правило, оптимальным индексом для запроса является индексирование всего в предложении where в порядке уменьшения селективности, а затем всего в order by в порядке уменьшения селективности, а затем всего того, что вы выбираете, но еще не выбрали индексируются. Это означает, что вы будете когда-либо использовать индекс, а не таблицу за ним.

Однако этот метод может быть совершенно нелепым. Вам решать, как далеко вы хотите пойти.

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

Если, например, rule_pk является первичным ключом вашей таблицы, то, вероятно, будет достаточно индексировать этот столбец. Это будет означать, что вы выполняете уникальное сканирование индекса с последующим доступом к таблице по rowid.

Продолжая предполагать, что rule_pk является первичным ключом, start_time_local почти уникален, а остальные столбцы одинаково избирательны, индекс оптимальный будет выглядеть примерно так: (rule_pk, start_time_local, type_pk, this_.name, start_time_gmt, my_table_id). Это довольно смешно.

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

Также не забудьте собрать статистику после создания индекса, так как это может иметь большое значение:

dbms_stats.gather_table_stats( 'SCHEMA_NAME'
                             , 'TABLE_NAME'
                             , cascade => True
                             , method_opt => 'FOR ALL INDEXED COLUMNS'
                               );

должно быть достаточно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...