2016-07-29 6 views
1

Я получил эту таблицу, содержащую 7000 записейПочему проверка на null замедляет этот запрос?

DESc ARADMIN.V_PKGXMLCODE

Name     Null  Type   
--------------------- -------- ------------- 
REQUEST_ID   NOT NULL VARCHAR2(15) 
AVAILABILITY     VARCHAR2(69) 
XML_CODE      CLOB   
PACKAGENAME_UNIQUE    VARCHAR2(50) 
CATALOG      NUMBER(15)  
CHILD       VARCHAR2(255) 
CLASSIFICATION_SYSTEM   NUMBER(15)  
E_MAIL       VARCHAR2(69) 

Запрос

SELECT COUNT(*) FROM ARADMIN.V_PKGXMLCODE WHERE (CATALOG <> 0 AND CATALOG <> 2) AND (NOT (CHILD IS NULL)); 

занимает менее одной секунды.

Запрос

SELECT COUNT(*) FROM ARADMIN.V_PKGXMLCODE WHERE (CATALOG IS NULL OR (CATALOG <> 0 AND CATALOG <> 2)) AND (NOT (CHILD IS NULL)); 

занимает 23 секунд.

Объяснить план, однако утверждает, что он должен идти очень быстро ...

enter image description here

Что я могу сделать?

+0

Есть ли в первом запросе полное сканирование таблицы или есть индекс в поле4, который он может использовать? И если есть, была ли таблица неоднократно удалена (не усечена) и повторно заполнена вставками прямого пути (то есть с подсказкой '/ * + append * /')? –

+1

Как насчет плана для первого запроса? – nilsman

+0

Условие 'IS NULL' будет игнорировать индекс, поскольку вы не можете индексировать значения NULL. Хорошо, что вы, конечно, могли бы обмануть оптимизатор, установив постоянное значение вместе с столбцом NULLABLE при индексировании. Но, чтобы ответить в рамках вашего вопроса, ваш второй запрос пойдет за ** FULL TABLE SCAN **, если вы не обманете оптимизатора, как я сказал ранее. Ваш первый запрос может использовать индексы и избегать FTS. 1. Пожалуйста, опубликуйте план объяснения для первого запроса. 2. Обновлена ​​ли статистика? –

ответ

0

Это интересно. Я ожидаю, что запрос будет иметь такую ​​же производительность, потому что у Oracle есть хороший оптимизатор и его не следует путать с NULL.

Как эта версия имеет лучшую производительность?

select x1.cnt + x2.cnt + x3.cnt 
from (select count(*) as cnt 
     from MYTABLE 
     where field4 = 1 and child is not null 
    ) x1 cross join 
    (select count(*) as cnt 
     from MYTABLE 
     where field4 = 4 and child is not null 
    ) x2 cross join 
    (select count(*) as cnt 
     from MYTABLE 
     where field4 is null and child is not null 
    ) x3; 

Эта версия должна быть в состоянии воспользоваться индексом на MYTABLE(field4, child).

+0

Что такое x1 x2 x3? Он говорит ORA-00904: «X3»: неверный идентификатор? – Thomas

+0

@Thomas - это псевдонимы таблицы для встроенных просмотров; они должны быть «x3.cnt» и т. д. –

+0

ОК, я вижу. Это заняло 23 секунды. – Thomas

3

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

Первый запрос будет по-прежнему использовать индекс и выполнять так, как ожидалось. Но поскольку нулевые значения не индексируются, индекс не может использоваться для проверки состояния or field4 is null, поэтому он вернется к полному сканированию таблицы.

Это само по себе не должно быть проблемой здесь, поскольку полное сканирование таблицы из 7000 строк не должно занять много времени. Но так как это так долго, что-то еще происходит. Полное сканирование таблицы должно проверять каждый блок данных, выделенный для таблицы, чтобы увидеть, содержат ли они какие-либо строки, и время, которое он принимает, предполагает, что существует намного больше блоков, чем вам нужно иметь 7000 строк, даже с встроенным хранилищем CLOB.

Самый простой способ получить много пустых блоков данных - это иметь много данных, а затем удалить большую часть его. Но я считаю, что вы сказали в недавно удаленном комментарии к более раннему вопросу о том, что производительность была в порядке и ухудшилась. Это может произойти, если вы делаете direct-path inserts, особенно если вы обновляете данные, удалив их, а затем вставляя новые данные в режим прямого пути. Вы можете сделать это со вставками, которые содержат подсказку /*+ append */; или параллельно; или через SQL * Loader. Каждый раз, когда вы делали это, знак высокой воды двигался, поскольку старые пустые блоки не могли быть повторно использованы; и каждый раз производительность запроса, который проверяет нулевые значения, немного ухудшится. После много итераций, которые действительно начнут складываться.

Вы можете проверить словарь данных, чтобы узнать, сколько места выделено вашей таблице (user_segments и т. Д.) И сравнить это с размером данных, которые вы на самом деле имеете. Вы можете сбросить HWM, восстановив таблицу, например.г, выполнив: (! предпочтительно в окне обслуживания)

alter table mytable move; 

В демке я провел цикл прямого пути вставки и удаления 7000 строк более ста раз, а затем побежал как ваши запросы , Первое заняло 0,06 секунды (большая часть из которых - служебные данные SQL Devleoper); второе заняло 1.260. (Я также управлял Гордоном, который получил аналогичное время, поскольку он все еще должен делать FTS). С большим количеством итераций разница станет еще более заметной, но у меня закончилось пространство ... Затем я сделал alter table move и повторно выполнил второй запрос, который затем занял 0,05 секунды.

+0

Итак, вы предлагаете мне изменить таблицу ARADMIN.V_PCKXMLCODE move; ? – Thomas

+0

Или перестройте его каким-либо другим способом - но вы, вероятно, не должны этого делать, пока люди могут получить доступ к нему. Я пытаюсь думать о запросе, который покажет, что это определенно проблема первой, и я не придумал лучше, чем просмотр «user_segments» - реальный администратор баз данных может обмануть идею. Вам также необходимо определить, действительно ли загружаются прямые пути; если это так, то проблема будет просто постепенно возвращаться. Как поддерживаются данные в таблице? И от его имени ... это на самом деле взгляд? Ну, да, в плане говорится, что фактическая таблица T111 - так, как поддерживается * that *? –

+0

Я пошел вперед и запустил запрос на таблицу, к которой обращается просмотр. Точно такие же результаты. Попытка выяснить, как данные поддерживаются. – Thomas

Смежные вопросы