2015-10-14 4 views
0

У меня есть запрос на выборку, которая занимает много времени:группа Oracle по занимает много времени

select user_id, variable, round(AVG(v_Score),1) v_score 
    from TEST_1M_SCORE_V1 where clock between 1 and 12 group by user_id, variable 

Эта таблица - TEST_1M_SCORE_V1 имеет 260,000,000 строк.

Есть ли другой способ написания группового предложения, чтобы он работал быстрее?

определения таблицы:

Name   Null Type   
------------- ---- ------------- 
USER_ID    NUMBER   
CLOCK    NUMBER   
VARIABLE   VARCHAR2(255) 
V_SCORE   NUMBER  
+0

Вы можете попробовать указатель на 'clock', если это условие очень избирательно. –

+0

Показать определение таблицы, включая индексы. Скомпонуемый индекс на 'clock, user_id, variable' был бы полезен – Mihai

+0

У меня его уже есть. – dang

ответ

2

Это два ответа, а не один, в зависимости от данных. Это ваш запрос:

select user_id, variable, round(AVG(v_Score), 1) as v_score 
from TEST_1M_SCORE_V1 
where clock between 1 and 12 
group by user_id, variable; 

Вариант 1 является то, что относительно небольшое число строк удовлетворяют условию where - где «сравнительно мало», безусловно, не более, чем несколько процентов. В этом случае полезен индекс на TEST_1M_SCORE_V1(clock). Вы можете расширить это значение до TEST_1M_SCORE_V1(clock, user_id, variable, score), для индекса покрытия. Oracle необходимо будет выполнить всю работу для group by, но только на меньшее количество данных.

Вариант 2 - когда количество строк удовлетворяет условию where. В этом случае вы хотите, чтобы Oracle выполнила полное сканирование индекса для group by. Проблема в том, что статья where. Один из подходов состоит в том, чтобы включить его в индекс, используя индекс на основе функций. Однако это очень специфично (работает 1 и 12, но не 1 и 11).

Вместо написать запрос как:

select user_id, variable, 
     round(AVG(case when clock between 1 and 12 then v_Score end), 1) as v_score 
from TEST_1M_SCORE_V1 
group by user_id, variable 
having sum(case when clock between 1 and 12 then 1 else 0 end) > 0; 

(. Предложение having не может быть необходимым, в зависимости от того, насколько вы заботитесь о user_id/variable комбо где avg() будут NULL)

Этот запрос эквивалентен оригиналу. Кажется, что он делает больше работы, но эта работа сильно оптимизирована для сканирования индекса по: TEST_1M_SCORE_V1(user_id, variable, clock, v_score). Идея заключается в том, что Oracle может считывать индекс, чтобы делать group by и вычисления в одно и то же время. Ему никогда не нужно искать данные в исходном наборе данных, и ему никогда не нужно обрабатывать group by с использованием алгоритма хеширования или сортировки.

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