Вопрос

У меня есть эта таблица:

create table demo (
    key number(10) not null,
    type varchar2(3) not null,
    state varchar2(16) not null,
    ... lots more columns ...
)

И этот индекс:

create index demo_x04 on demo(key, type, state);

Когда я запускаю этот запрос

select * from demo where key = 1 and type = '003' and state = 'NEW'

EXPLAIN PLAN показывает, что он выполняет полное сканирование таблицы. Поэтому я уронил индекс и создал его снова. EXPLAIN PLAN Все еще говорит полное сканирование стола. Как это может быть?

Некоторый фон: это исторические данные, так что это происходит, так это то, что я смотрю ряд с состоянием CLEARED и вставьте новый ряд в состояние NEW (плюс я копирую несколько значений из старой строки). Старый ряд затем обновляется до USED. Анкет Так что стол всегда растет. Я заметил, что кардинальность индекса составляет 0 (несмотря на то, что у меня тысячи различных значений). После воссоздания кардинальность росла, но CBO не понравился индекс лучше.

На следующее утро Oracle внезапно понравилось индекс (вероятно, спал над ним) и начал использовать его, но не надолго. Через некоторое время обработка упала с 50 рядов до 3 рядов/с, и я снова увидел «полное сканирование таблицы». Что здесь происходит?

В моем случае мне нужно обработать около миллиона строк. Я совершаю изменения в партиях ок. 50. Есть ли какая -то команда, которую я должен запустить после обновления/повторного индекса или что -то в этом роде?

Я на Oracle 10G.

РЕДАКТИРОВАТЬ] У меня есть 969'491 отдельные ключи в этой таблице, 3 типа и 3 состояния.

Это было полезно?

Решение

Что произойдет, если вы указали подсказку индекса? Попробуй это:

SELECT /*+ INDEX (demo demo_x04) */ * 
  FROM demo 
 WHERE key = 1 
   AND type = '003' 
   AND state = 'NEW';

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

Добавьте подсказку и посмотрите, дает ли Plan Exply Plan другой план, и запрос работает лучше.

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

Чтобы обновить статистику для таблицы, используйте dmbs_stats.gather_table_stats упаковка.

Например:

exec dbms_stats.gather_table_stats ('the владелец', 'demo');

Другие советы

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

Попробуй это:

select last_analyzed, num_rows 
from user_tables
where table_name = 'DEMO';

Num_rows сообщает вам, сколько рядов думает, что Oracle считает, что таблица содержит.

«На следующее утро Oracle внезапно понравилось индекс (вероятно, спал над ним)», вероятно, DBMS_STATS работает в течение ночи.

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

Второе - когда запрос такой, что индекс не может быть практически использован.

"select * from demo where key = 1 and type = '003' and state = 'NEW'"

Вы на самом деле используете литералы, жестко кодируемые в запросе. Если нет, то ваши переменные данные дата могут быть неверными (например, ключ - это символ). Это потребовало бы преобразования цифрового ключа в символ для сравнения, что сделало бы индекс почти бесполезным.

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

Комментарий к обработке, которую вы описываете: звучит так, как будто вы делаете обработку с рядовыми рядами с прерывистыми коммитами, и я бы призвал вас переосмыслить это, если сможете. Механизм обновления/вставки вполне может быть преобразован в оператор MERGE, и весь набор данных может быть обработан в одном операторе с одним коммитом в конце. Это почти наверняка будет быстрее и использовать меньше ресурсов, чем ваш текущий метод.

Всегда ли значение ключа столбца 1? Если это так, я не уверен, что консалтинг индекса оптимизирует запрос, так как каждая строка должна быть рассмотрена в любом случае. Если так, объявите индекс без столбца ключа. Вы также можете попробовать:

select key, type, state from demo where key = 1 and type = '003' and state = 'NEW'

Что (если я предполагаю правильное), все равно нужно смотреть на каждую строку, но которая может перейти к индексу, поскольку все столбцы в наборе результатов теперь покрываются.

Я просто угадываю на основе вашего утверждения, что индекс показывает кардинальность 0.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top