2013-05-16 3 views
0

Я хотел бы улучшить производительность следующего в агрегированном запросе.Обновление производительности в сводном запросе

На T_Search_Detail с 30 миллионами записей ниже запрос занимает 12 секунд для выполнения? можно ли его лучше написать, предложения по повышению производительности?

Explain Plan:

Execution Plan 
---------------------------------------------------------- 
Plan hash value: 651646209 
-------------------------------------------------------------------------------------------------- 
| Id | Operation      | Name   | Rows | Bytes | Cost (%CPU)| Time  | 
-------------------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT    |     |  3 | 42 | 27948 (1)| 00:05:36 | 
| 1 | SORT GROUP BY     |     |  3 | 42 | 27948 (1)| 00:05:36 | 
| 2 | VIEW       |     | 56 | 784 | 27947 (1)| 00:05:36 | 
| 3 | HASH GROUP BY    |     | 56 | 1344 | 27947 (1)| 00:05:36 | 
|* 4 |  TABLE ACCESS BY INDEX ROWID| T_SEARCH_DETAIL | 898 | 21552 | 27946 (1)| 00:05:36 | 
|* 5 |  INDEX RANGE SCAN   | INDEX_CREATE_DT | 1254K|  | 3451 (1)| 00:00:42 | 
-------------------------------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 
    4 - filter("TSD"."MATCH_SOURCE" IS NOT NULL AND "TSD"."MATCH_TYPE" IS NOT NULL AND 
       "TSD"."MATCH_TYPE" LIKE '%Exact%') 
    5 - access("TSD"."CREATE_DT">=TO_DATE(' 2012-12-11 00:00:00', 'syyyy-mm-dd 
       hh24:mi:ss') AND "TSD"."CREATE_DT"<TO_DATE(' 2013-04-23 00:00:00', 'syyyy-mm-dd 
       hh24:mi:ss')) 

Таблица DDL: enter image description here

Этот запрос использует две таблицы T_Search и T_Search_detail с foreign_key как match_id.

SELECT ms, 
     SUM(ct) 
FROM  (SELECT tsd.match_source ms, 
        tsd.match_type  mt, 
        COUNT(tsd.search_id) ct 
     FROM  t_search ts, 
        t_search_detail tsd 
     WHERE tsd.match_source IS NOT NULL 
     AND  tsd.match_type IS NOT NULL 
     AND  ts.match_id    = tsd.match_id 
     AND  tsd.match_type   LIKE '%Exact%' 
     AND 
        (
          tsd.create_dt >= to_date('12/11/2012', 'MM/DD/YYYY') 
        AND  tsd.create_dt < (to_date('04/22/2013', 'MM/DD/YYYY')+1) 
       ) 
     GROUP BY tsd.match_source, 
        tsd.match_type 
     ) 
GROUP BY ms 
ORDER BY ms DESC 
+3

Вы должны предоставить план объяснения и определение таблицы, как минимум, в противном случае никто не сможет разумно помочь вам. – Ben

+0

Можете ли вы предоставить некоторые показатели производительности? Время, память и т. Д. –

+0

Просьба также указать размеры таблиц и информацию об индексах. –

ответ

2

Если было бы целесообразно, чтобы получить доступ к «% Exact%» строк через индекс, то вы можете сделать это с помощью функции на основе индекса:

create index ... on ... (case Coalesce(InStr(match_type,'Exact'),0) when 0 then null else 1 end) 

Это будет включают в индексе только те строки, где тип соответствия содержит строку «Целую», и вы бы запрос на:

where ... and 
     (case Coalecse(InStr(match_type,'Exact'),0) when 0 then null else 1 end) = 1 

вы можете объединить поиск по «Exact» с п индекс даты с:

create index ... on ... (case Coalesce(InStr(match_type,'Exact'),0) when 0 then null else create_dt end) 

... который бы индекс create_dt только для строк, где тип_сопоставления включает «Целую».

Вы бы запросить с:

case Coalesce(InStr(match_type,'Exact'),0) when 0 then null else create_dt end >= to_date('12/11/2012', 'MM/DD/YYYY') and 
case Coalesce(InStr(match_type,'Exact'),0) when 0 then null else create_dt end < (to_date('04/22/2013', 'MM/DD/YYYY')+1) 
+0

умный, я попробую! Благодарю. – Narayan

+0

дошло до 9 секунд! благодаря – Narayan

1

Во-первых, вам не нужны два уровня агрегации для того, что вы делаете. Вы можете просто агрегировать на match_source и подсчитать количество совпадающих записей.

Вот упрощенная версия запроса, используя правильный синтаксис объединения:

SELECT tsd.match_source ms, COUNT(tsd.search_id) ct 
FROM t_search ts join 
    t_search_detail tsd 
    on ts.match_id = tsd.match_id 
WHERE tsd.match_source IS NOT NULL AND 
     tsd.match_type IS NOT NULL AND 
     tsd.match_type LIKE '%Exact%' and 
     tsd.create_dt >= to_date('12/11/2012', 'MM/DD/YYYY') and 
     tsd.create_dt < (to_date('04/22/2013', 'MM/DD/YYYY')+1) 
GROUP BY tsd.match_source; 

Далее, это выглядит как стол t_search не используется вообще. Он может использоваться для фильтрации или может увеличить количество строк. Однако, если предположить, что все в t_search_detail матчах ровно один ряд в t_search, то у вас есть:

SELECT tsd.match_source ms, COUNT(tsd.search_id) ct 
FROM t_search_detail tsd 
WHERE tsd.match_source IS NOT NULL AND 
     tsd.match_type IS NOT NULL AND 
     tsd.match_type LIKE '%Exact%' and 
     tsd.create_dt >= to_date('12/11/2012', 'MM/DD/YYYY') and 
     tsd.create_dt < (to_date('04/22/2013', 'MM/DD/YYYY')+1) 
GROUP BY tsd.match_source; 

При этом, вы можете получить прирост производительности с использованием индекса, такие как t_search_detail(match_source, match_type, create_dt):

CREATE INDEX tsearchdetail_matchsource_matchtype_createdt 
     ON t_search_detail(match_source, match_type, create_dt); 

Он появляется что этот запрос должен будет выполнить поиск по всем записям, которые соответствуют дате. Разверните список match_type формы '%EXACT%' в список конечных пользователей? Если это так, то изменить эту строку из where в:

where . . . and match_type in (<list of exact match types>) . . . 

Затем вы хотите индекс на (match_type, create_dt). Тем не менее, это значительно улучшит производительность, только если большинство типов соответствия не являются «точными». Вы можете просто быть в положении, когда вам нужно обрабатывать множество и много записей, что может занять несколько секунд.

+0

Спасибо, Гордон Линофф, индексы уже присутствуют на этих столбцах, любые другие мысли? – Narayan

+0

@ Нараян. , , Ответ очень специфичен в отношении того, что один индекс имеет три столбца в этом порядке. Наличие отдельного индекса для каждого столбца не принесет такой большой выгоды. –

+0

Почему это так? что делает заказ особенным, пожалуйста, объясните – Narayan

0

Помимо настройки самого SQL-монитора, монитор v $ sql_workarea_active во время выполнения запроса (и v $ sql_workarea впоследствии), чтобы узнать, использует ли ваш запрос временное табличное пространство для хранения, и если да, то ли вы используете одно- .

Многопроходные операции - это убийца с производительностью, и вы должны убедиться, что вы производите размер памяти, чтобы избежать этого, и предпочтительно избегать однопроходных операций. Для этого вам, возможно, придется переключить сеанс на ручное управление памятью или посмотреть общее распределение размеров PGA и SGA через их соответствующие представления советника кэша.

http://docs.oracle.com/cd/E11882_01/server.112/e16638/memory.htm#i49320

+0

Я буду смотреть на эти указатели, спасибо – Narayan