Performance Oracle日期索引速度慢。如果没有它,查询速度将提高300倍
我有一个Oracle查询,运行时间为10分钟或更长,如下所示:Performance Oracle日期索引速度慢。如果没有它,查询速度将提高300倍,performance,oracle,date,indexing,query-optimization,Performance,Oracle,Date,Indexing,Query Optimization,我有一个Oracle查询,运行时间为10分钟或更长,如下所示: select r.range_text as duration_range, nvl(count(c.call_duration),0) as calls, nvl(SUM(call_duration),0) as total_duration from call_duration_ranges r left join big_table c
select
r.range_text as duration_range,
nvl(count(c.call_duration),0) as calls,
nvl(SUM(call_duration),0) as total_duration
from
call_duration_ranges r
left join
big_table c
on c.call_duration BETWEEN r.range_lbound AND r.range_ubound
and c.aaep_src = 'MAIN_SOURCE'
and c.calltimestamp_local >= to_date('01-02-2014 00:00:00' ,'dd-MM-yyyy HH24:mi:ss')
AND c.calltimestamp_local <= to_date('28-02-2014 23:59:59','dd-MM-yyyy HH24:mi:ss')
and c.destinationnumber LIKE substr( 'abc:1301@company.com:5060;user=phone',1,8) || '%'
group by
r.range_text
order by
r.range_text
使用destinationnumber索引查询2天:
0 SELECT STATEMENT ALL_ROWS 329382 1218 14
1 SORT GROUP BY 329382 1218 14
2 MERGE JOIN OUTER 329381 1218 14
3 SORT JOIN 4 308 14
4 TABLE ACCESS FULL CALL_DURATION_RANGES ANALYZED 3 308 14
5 FILTER
6 SORT JOIN 329377 65 1
7 TABLE ACCESS BY GLOBAL INDEX ROWID BIG_TABLE ANALYZED 329376 65 1
8 INDEX RANGE SCAN IDX_CDR_CALLTIMESTAMP_LOCAL ANALYZED 1104 342104
0 SELECT STATEMENT ALL_ROWS 11 1218 14
1 SORT GROUP BY 11 1218 14
2 MERGE JOIN OUTER 10 1218 14
3 SORT JOIN 4 308 14
4 TABLE ACCESS FULL CALL_DURATION_RANGES ANALYZED 3 308 14
5 FILTER
6 SORT JOIN 6 65 1
7 TABLE ACCESS BY GLOBAL INDEX ROWID BIG_TABLE ANALYZED 5 65 1
8 INDEX RANGE SCAN IDX_DESTINATIONNUMBER_PART ANALYZED 4 4
查询一个月,取消destinationnumber索引--完全扫描:
0 SELECT STATEMENT ALL_ROWS 824174 1218 14
1 SORT GROUP BY 824174 1218 14
2 MERGE JOIN OUTER 824173 1218 14
3 SORT JOIN 4 308 14
4 TABLE ACCESS FULL CALL_DURATION_RANGES ANALYZED 3 308 14
5 FILTER
6 SORT JOIN 824169 65 1
7 PARTITION RANGE ALL 824168 65 1
8 TABLE ACCESS FULL BIG_TABLE ANALYZED 824168 65 1
不过,这似乎与直觉相反——指数让事情变得如此缓慢
只有当您不了解索引是如何工作的时,才会违反直觉
索引对于检索单个行很有用。它们不适合检索大量记录。您没有费心提供任何指标,但您的查询似乎涉及了大量行。在这种情况下,全表扫描或其他基于set=的操作将更加有效
调整日期范围查询很棘手,因为数据库很难知道有多少记录位于这两个界限之间,无论我们的统计数据是多么最新。(当日期界限可能发生变化时,调整更为棘手——一天与一个月或一年是不同的事情。)因此,我们经常需要利用我们对数据的了解来帮助优化器 不要认为使用“+0”是未来最好的解决方案 为什么不呢?几十年来,人们一直在使用这种技术来避免在特定查询中使用索引 然而,有更多的现代解决方案。未记录的基数提示是:
select /*+ cardinality(big_table,10000) */
。。。应该足以阻止优化器使用索引-前提是您为查询中的所有表收集了准确的统计数据
或者,您可以强制优化器使用
select /*+ full(big_table) */
无论如何,您无法对索引执行任何操作来更改数据库的工作方式。分区可以让事情变得更快,但我想如果你的组织购买了这个软件,你可能已经在使用它了
不过,这似乎与直觉相反——指数让事情变得如此缓慢
只有当您不了解索引是如何工作的时,才会违反直觉
索引对于检索单个行很有用。它们不适合检索大量记录。您没有费心提供任何指标,但您的查询似乎涉及了大量行。在这种情况下,全表扫描或其他基于set=的操作将更加有效
调整日期范围查询很棘手,因为数据库很难知道有多少记录位于这两个界限之间,无论我们的统计数据是多么最新。(当日期界限可能发生变化时,调整更为棘手——一天与一个月或一年是不同的事情。)因此,我们经常需要利用我们对数据的了解来帮助优化器 不要认为使用“+0”是未来最好的解决方案 为什么不呢?几十年来,人们一直在使用这种技术来避免在特定查询中使用索引 然而,有更多的现代解决方案。未记录的基数提示是:
select /*+ cardinality(big_table,10000) */
。。。应该足以阻止优化器使用索引-前提是您为查询中的所有表收集了准确的统计数据
或者,您可以强制优化器使用
select /*+ full(big_table) */
无论如何,您无法对索引执行任何操作来更改数据库的工作方式。分区可以让事情变得更快,但我想如果您的组织购买了,您可能已经在使用它了。以下是使用索引减慢查询速度的原因:
APCs answer展示了如果优化器在正确的统计数据下仍然生成错误的计划,如何使用提示将其引导到正确的方向。以下是使用索引减慢查询速度的原因: