У меня есть таблица с 250K строк в моей тестовой базе данных. (В производстве несколько сотен миллионов, мы можем наблюдать ту же проблему.) Таблица имеет строковый идентификатор nvarchar2 (50), а не ноль, с уникальным индексом (это не PK).
Идентификаторы состоят из первой части, имеющей 8 различных значений в моей тестовой базе данных (и около тысячи в производстве), затем знака @ и, наконец, числа длиной от 1 до 6 цифр. Например, может быть 50 тысяч строк, которые начинаются с 'ABCD_BGX1741F_2006_13_20110808.xml @', а за ним следуют 50 тысяч различных номеров.
Когда я запрашиваю одну строку на основе ее идентификатора, количество элементов оценивается как 1, стоимость очень низкая, она работает нормально. Когда я запрашиваю более одной строки с несколькими идентификаторами в выражении IN или выражении OR, оценки индекса совершенно неверны, поэтому используется полное сканирование таблицы. Если я намекаю на индекс с подсказкой, он очень быстрый, полное сканирование таблицы выполняется на порядок медленнее (и намного медленнее в производстве). Так что это проблема оптимизатора.
В качестве теста я продублировал таблицу (в той же схеме + табличное пространство) с точно таким же DDL и точно таким же содержимым. Я воссоздал уникальный индекс в первой таблице для хорошей меры и создал точно такой же индекс в таблице клонов. Я сделал DBMS_STATS.GATHER_SCHEMA_STATS('schemaname',estimate_percent=>100,cascade=>true);
. Вы даже можете видеть, что имена индексов являются последовательными. Таким образом, теперь единственное различие между этими двумя таблицами состоит в том, что первая была загружена в произвольном порядке в течение длительного периода времени, когда на диске были разбросаны блоки (в табличном пространстве вместе с несколькими другими большими таблицами), вторая была загружена как одна пакетная. INSERT-SELECT. Кроме этого, я не могу представить никакой разницы. (Исходная таблица была уменьшена с момента последнего большого удаления, и после этого не было ни одного удаления.)
Вот планы запросов для таблицы больных и клонов (строки под черной кистью одинаковы по всей картинке, а также под серой кистью.):
(В этом примере есть 1867 строк, которые начинаются с идентификатора, выделенного черным цветом. 2-строчный запрос дает мощность 1867 * 2, 3-строчный запрос создает мощность 1867 * 3 и т. Д. По совпадению, Oracle, похоже, не заботится о конце идентификаторов.)
Что может вызвать такое поведение? Очевидно, было бы довольно дорого воссоздать таблицу в производстве.
USER_TABLES: http://i.stack.imgur.com/nDWze.jpg USER_INDEXES: http://i.stack.imgur.com/DG9um.jpg Я изменил только имя схемы и табличного пространства. Вы можете видеть, что имена таблиц и индексов такие же, как на скриншоте плана запросов.