#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:
Выполните все эти:
-
Создайте индексы для полей, которые являются частью вашего where.
-
Вместо использования умножения по Декарту (которое вы используете в данный момент) используйте объединения.
-
В вашем предложении where сначала поместите более быстрые и менее вероятные логические операнды. Например, где A и B имеют значение true, если оба они имеют значение true, поэтому, если A равно false, B вообще не будет вычисляться, и вы выиграете много времени. Это может быть разница в выполнении сотен тысяч логических проверок или в том, чтобы не делать этого, так что, конечно, это оптимизация.
Я не переписываю ваш запрос, потому что я не могу сказать, какие операнды менее вероятны, какие операнды быстрее, вам придется измерить каждый операнд и упорядочить их таким образом, чтобы сначала вычислялись менее вероятные или более быстрые операнды, и надеяться, что остальные не будут вычислены.
Я надеюсь, что это поможет.
Комментарии:
1. Это так. Спасибо. Принято. Проголосовал за.