Oracle 10G запрашивает грязные данные и никогда не возвращает

#sql

#sql

Вопрос:

Я пытаюсь составить отчет по трем таблицам, в которые данные загружаются ежедневно. Проблема в том, что данные «грязные» (см. Предложение WHERE). Хотя у меня есть индекс в каждой из трех таблиц для столбца, с которым я выполняю equijoin, запрос никогда не возвращается.

 SELECT 
A.SITE || ',' ||
A.SCRIPT || ',' ||
A.TESTRESULT || ',' ||
A.BISTERROR || ',' ||
A.HDDMANUFACTURER || ',' ||
A.TESTDATE || ',' ||
A.STB_MODEL || ',' ||
A.RECEIVERID || ',' ||
B.STB_MODEL || ',' ||
B.STB_MANUFACTURER || ',' ||
B.STB_MFRDATE || ',' ||
B.SW_VERSION || ',' ||
B.SW_NAME || ',' ||
B.HW_VERSION || ',' ||
B.RECEIVERID || ',' ||
C.HDDMODELNUMBER || ',' ||
C.HDDSERIALNUMBER || ',' ||
C.DISKPORT || ',' ||
C.DISKSIZE || ',' ||
C.SECTORSIZE || ',' ||
C.POWERONHOURS || ',' ||
C.CURRENTTEMP || ',' ||
MAX(TRUNC(A.LOAD_DATE)) 
FROM 
HDD_SMARTLOG_FILEINFO A, 
HDD_SMARTLOG_BOXINFO B, 
HDD_SMARTLOG_DISKINFO C 
WHERE 
A.FILENAME=B.FILENAME 
AND 
B.FILENAME=C.FILENAME 
AND 
INSTR(TRANSLATE(A.RECEIVERID,'0123456789','XXXXXXXXXX'),'X') != LENGTH(A.RECEIVERID) 
AND 
INSTR(TRANSLATE(B.RECEIVERID,'0123456789','XXXXXXXXXX'),'X') != LENGTH(B.RECEIVERID) 
AND 
LOWER(C.DISKPORT)='internal' 
AND 
A.SITE IS NOT NULL OR A.SITE <> '' 
AND 
A.BISTERROR IS NOT NULL OR A.BISTERROR <> '' 
AND 
B.STB_MODEL IS NOT NULL OR B.STB_MODEL <> '' 
AND 
B.SW_VERSION IS NOT NULL OR B.SW_VERSION <> '' 
AND 
C.POWERONHOURS IS NOT NULL OR C.POWERONHOURS <> '' 
AND 
C.CURRENTTEMP IS NOT NULL OR C.CURRENTTEMP <> '' 
AND 
INSTR(TRANSLATE(C.POWERONHOURS,'0123456789','XXXXXXXXXX'),'X') != LENGTH(C.POWERONHOURS) 
AND 
INSTR(TRANSLATE(C.CURRENTTEMP,'0123456789','XXXXXXXXXX'),'X') != LENGTH(C.CURRENTTEMP) 
GROUP BY 
A.SITE, 
A.SCRIPT, 
A.TESTRESULT, 
A.BISTERROR, 
A.HDDMANUFACTURER, 
A.TESTDATE, 
A.STB_MODEL, 
A.RECEIVERID, 
B.STB_MODEL, 
B.STB_MANUFACTURER, 
B.STB_MFRDATE, 
B.SW_VERSION, 
B.SW_NAME, 
B.HW_VERSION, 
B.RECEIVERID, 
C.HDDMODELNUMBER, 
C.HDDSERIALNUMBER, 
C.DISKPORT, 
C.DISKSIZE, 
C.SECTORSIZE, 
C.POWERONHOURS, 
C.CURRENTTEMP;
  

Раньше это работало около месяца назад, когда у нас ежедневно было менее 100 тыс. записей. Сейчас мы обрабатываем /- 300 тыс. ежедневно.

Как я могу оптимизировать этот запрос. Мой босс хочет, чтобы это запускалось ежедневно. Не могли бы вы, пожалуйста, дать несколько указаний?

Заранее спасибо!

Ответ №1:

Выполните все эти:

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

  2. Вместо использования умножения по Декарту (которое вы используете в данный момент) используйте объединения.

  3. В вашем предложении where сначала поместите более быстрые и менее вероятные логические операнды. Например, где A и B имеют значение true, если оба они имеют значение true, поэтому, если A равно false, B вообще не будет вычисляться, и вы выиграете много времени. Это может быть разница в выполнении сотен тысяч логических проверок или в том, чтобы не делать этого, так что, конечно, это оптимизация.

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

Я надеюсь, что это поможет.

Комментарии:

1. Это так. Спасибо. Принято. Проголосовал за.