Oracle 10g - оптимизировать, ГДЕ НЕ НУЛЬ

16
задан Jason Punyon 6 April 2009 в 14:00
поделиться

7 ответов

Оптимизатор думает, что полное сканирование таблицы будет лучше.

Если существуют только некоторые NULL строки, оптимизатор является правильным.

Если Вы абсолютно уверены, что индексный доступ будет быстрее (то есть, у Вас есть больше, чем 75% строки с col1 IS NULL), затем подскажите свой запрос:

SELECT  /*+ INDEX (t index_name_on_col1) */
        *
FROM    mytable t
WHERE   col1 IS NOT NULL

Почему 75%?

Поскольку использование INDEX SCAN получать значения, не покрытые индексом, подразумевает скрытое соединение на ROWID, который стоит о 4 времена так же как сканирование таблицы.

Если индексный диапазон включает больше, чем 25% из строк сканирование таблицы обычно быстрее.

Как упомянуто Tony Andrews, кластеризация фактора является более точным методом для измерения этого значения, но 25% все еще хорошее эмпирическое правило.

24
ответ дан 30 November 2019 в 16:14
поделиться

Если бы Вы делаете выбор *, то имело бы смысл делать сканирование таблицы вместо того, чтобы использовать индекс. Если Вы знаете, какими столбцами Вы интересуетесь, Вы могли создать покрытый индекс с теми colums плюс тот, который Вы применяете, условие NOT NULL.

2
ответ дан 30 November 2019 в 16:14
поделиться

Оптимизатор примет свое решение на основе относительной стоимости полного сканирования таблицы и использования индекса. Это главным образом сводится, сколько блоков должно будет быть считано для удовлетворения запроса. 25%/75 эмпирических правил %, упомянутых в другом ответе, упрощенны: в некоторых случаях полное сканирование таблицы будет иметь смысл даже получать 1% строк - т.е. если те строки, оказывается, распространены вокруг многих блоков.

Например, рассмотрите эту таблицу:

SQL> create table t1 as select object_id, object_name from all_objects;

Table created.
SQL> alter table t1 modify object_id null;

Table altered.

SQL> update t1 set object_id = null
  2  where mod(object_id,100) != 0
  3  /

84558 rows updated.

SQL> analyze table t1 compute statistics;

Table analyzed.

SQL> select count(*) from t1 where object_id is not null;

  COUNT(*)
----------
       861    

Как Вы видите, только приблизительно 1% строк в T1 имеет непустой указатель object_id. Но из-за пути я создал таблицу, эта 861 строка будет распространена более или менее равномерно вокруг таблицы. Поэтому запрос:

select * from t1 where object_id is not null;

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

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

SQL> select clustering_factor from user_indexes where index_name='T1_IDX';

CLUSTERING_FACTOR
-----------------
              460

Это значение 460 довольно высоко (по сравнению с этой 861 строкой в индексе) и предполагает, что будет использоваться полное сканирование таблицы. См. эту статью DBAZine о кластеризирующихся факторах.

16
ответ дан 30 November 2019 в 16:14
поделиться

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

Большинство индексов B-дерева не хранят пустые записи. Растровые индексы делают хранят нулевые записи.

Итак, если у вас есть:

выберите * из mytable где mycolumn равно нулю

, и у вас есть стандартный индекс B-дерева для mycolumn , тогда запрос не может использовать индекс, так как «ноль» отсутствует в index.

(Если индекс относится к нескольким столбцам, и один из индексированных столбцов не равен NULL, то в индексе будет запись.)

1
ответ дан 30 November 2019 в 16:14
поделиться

Создайте индекс на том столбце.

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

ocdecio отвечают:

Если бы Вы делаете выбор *, то имело бы смысл делать сканирование таблицы вместо того, чтобы использовать индекс.

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

0
ответ дан 30 November 2019 в 16:14
поделиться

Также стоит проверить, актуальна ли статистика Oracle в таблице. Возможно, он не знает, что полное сканирование таблицы будет медленнее.

0
ответ дан 30 November 2019 в 16:14
поделиться

См. http://www.oracloid.com/2006/05 / using-index-for-is-null /

Если ваш индекс находится в одном поле, он НЕ будет использоваться. Попробуйте добавить в индекс фиктивное поле или константу:

create index tind on t(field_to_index, 1); 
-1
ответ дан 30 November 2019 в 16:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: