我想在聚合查询中提高以下性能。
在有30万条记录的T_Search_Detail上,查询下面需要12秒才能执行?可以写得更好,提高绩效的建议吗?
解释计划:
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:
此查询使用两个表 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
答案 0 :(得分:2)
如果通过索引访问“%Exact%”行是值得的,那么您可以通过使用基于函数的索引来实现:
create index ... on ... (case Coalesce(InStr(match_type,'Exact'),0) when 0 then null else 1 end)
这将在索引中仅包含匹配类型包含字符串“Exact”的行,您将查询:
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)
...仅为match_type包含“Exact”的行索引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)
答案 1 :(得分: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)
上的索引。但是,只有当大多数匹配类型不是“精确”时,这才能显着提高性能 - 您可能只处于需要处理大量记录的位置,这可能需要几秒钟。
答案 2 :(得分:0)
除了SQL调优本身,在查询执行期间监视v $ sql_workarea_active(以及之后的v $ sql_workarea)以查看您的查询是否使用临时表空间进行存储,如果是,则判断您是单个还是多个传递操作
多遍操作是性能杀手,您需要确保调整内存以避免这些操作,并且最好避免单遍操作。为此,您可能必须将会话切换到手动内存管理,或者通过各自的缓存顾问程序视图查看PGA和SGA大小的总体分配。
http://docs.oracle.com/cd/E11882_01/server.112/e16638/memory.htm#i49320