Oracle: индексы не используются - PullRequest
2 голосов
/ 25 августа 2011

У меня есть запрос, который не использует мои индексы.Кто-то может сказать почему?

explain plan set statement_id = 'bad8' for
select
  g1.g1id,a.a1id from atable a, 
(
 select
   phone,address,g1id from gtable g
 where
   g.active = 0 and
   (g.name is not null) AND 
   (SYSDATE - g.CTIME <= 2*365)
) g1
where
(
  (a.phone.ph1 = g1.phone.ph1 and
   a.phone.ph2 = g1.phone.ph2 and
   a.phone.ph3 = g1.phone.ph3
  )
  OR
  (a.address.ad1 = g1.address.ad1 and a.address.ad2 = g1.address.ad2)
) 

В обеих таблицах: atable, gtable у меня есть следующие индексы:
1. На phone.ph1, phone.ph2, phone.ph3
2. Вкл.address.ad1, address.ad2
телефон, адрес имеют пользовательские типы данных.
Использование Oracle 11g.

Вот запрос и вывод плана объяснения:

 SELECT cardinality "Rows",
      lpad(' ',level-1)||operation||' '||
      options||' '||object_name "Plan"
 FROM PLAN_TABLE
 CONNECT BY prior id = parent_id
       AND prior statement_id = statement_id
 START WITH id = 0
       AND statement_id = 'bad8'
 ORDER BY id;

Результат:

>   Rows           Plan    
     490191190  SELECT STATEMENT  
>       null          CONCATENATION  
>     490190502   HASH JOIN  
>     511841       TABLE ACCESS FULL gtable
>     41332965     PARTITION LIST ALL 
>     41332965      TABLE ACCESS FULL atable
>     688               HASH JOIN  
>     376893       TABLE ACCESS FULL gtable
>     41332965     PARTITION LIST ALL 
>     41332965      TABLE ACCESS FULL atable

Обе таблицы atable, gtable имеют более 10 миллионов строк в каждой.
Большинство значений в столбцах phone и address не повторяются.

Ответы [ 2 ]

3 голосов
/ 25 августа 2011

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

Сказав это, я полагаю, что основная причина, по которой ваши индексы не используются:

  • Вы не присоединяетесь напрямую с GTABLE / GLOBAL. Вместо этого вы присоединяетесь к представлению, имеющему три дополнительных предложения WHERE, которые не являются частью индекса и, следовательно, делают его менее эффективным в этом созвездии.

  • Условие JOIN включает ИЛИ, что затрудняет использование индексов.

Обновление:

Если бы Oracle использовал ваши индексы для объединения - что уже очень сложно из-за условия ИЛИ - это привело бы к огромному количеству ROWID. Для каждого ROWID он должен был получить полный ряд. Поскольку полное сканирование таблицы может быть в 50 раз быстрее, чем выборка по ROWID (я не знаю, какое значение использует Oracle), он будет использовать индексы, только если он точно знает, что объединение уменьшит количество строк до получить в 50 раз.

В вашем случае существуют остальные условия WHERE (g.active = 0, g.name не равно NULL, SYSDATE - g.CTIME <= 2 * 365), которые не представлены в индексах. Таким образом, они должны применяться после объединения и после выборки строк GTABLE. Это еще более затрудняет достижение результирующего набора в 50 раз меньше, чем полное сканирование таблицы. </p>

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

1 голос
/ 25 августа 2011

Мы можем сказать: «Ваш запрос не использует ваши индексы, потому что они не нужны».Хеш-соединение лучше.Чтобы использовать ваши индексы, оракулу необходимо полностью отсканировать их (4 индекса), сделать два объединения, сделать rowid или, и после этого прочитать из таблиц, вероятно, много блоков.Если он считает, что в результате имеется много строк, CBO выполняет полное сканирование, потому что это быстрее.

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

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