Счетчик (1) из таблицы, содержащей миллион записей, медленен даже при параллельной (8) подсказке - PullRequest
2 голосов
/ 15 октября 2019

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

SELECT
 /*+ parallel(cs_salestransaction 8)
 index_ffs(cs_salestransaction CS_SALESTRANSACTION_COMPDATE)
 index_ffs(cs_salestransaction CS_SALESTRANSACTION_AK1) */
 COUNT(1)
FROM cs_salestransaction
WHERE processingunitseq=38280596832649217
AND (compensationdate BETWEEN DATE '28-06-17' AND DATE '26-01-18'
OR eventtypeseq IN (16607023626823731, 16607023626823732, 16607023626823733, 16607023626823734));

Вот план выполнения:

[[Execution plan]

Запрос дал результат, но для расчета 194 миллионов потребовалось 2 часа.

Изменения:


Код отредактирован так, чтобы добавить DATE для каждого предложения Littlefoot. Код редактируется с фактическими именами столбцов. Я новичок в переполнении стека, поэтому прикрепил план как изображение.

Ответы [ 2 ]

5 голосов
/ 15 октября 2019

Кроме того, если compensationdate равен DATE типу данных, не сравнивайте его с строками (потому что '28-JUL-17' является строкой) и заставляйте Oracle выполнять неявное преобразованиеи тратить время на ничего . Переключиться на

compensationdate BETWEEN date '2017-07-28' and date '2018-01-26'
0 голосов
/ 15 октября 2019

Наличие OR СОСТОЯНИЯ в выражении where игнорирует использование индекса в запросе. Вы должны избавиться от состояния ИЛИ. Для этого может быть несколько способов. Один из методов -

SELECT /*+ parallel(sales 8)
           index_ffs(sales ,sales_COMPDATE) 
           index_ffs(sales , sales_eventtypeseq )*/
       COUNT(1)
FROM sales 
WHERE processingunitseq=38
AND compensationdate BETWEEN TO_DATE('28-JUL-17') AND TO_DATE('26-JAN-18')
UNION ALL
SELECT /*+ parallel(sales 8)
           index_ffs(sales ,sales_COMPDATE) 
           index_ffs(sales , sales_eventtypeseq )*/
       COUNT(1)
FROM sales 
WHERE processingunitseq=38
AND compensationdate NOT BETWEEN TO_DATE('28-JUL-17') AND TO_DATE('26-JAN-18')  -- To avoid duplicates
AND eventtypeseq IN (1, 2, 3, 4);

. Для других предложений, пожалуйста, опубликуйте план выполнения запроса.

...