ORACLE中SQL查询优化研究
2012-01-11 17:07
393 查看
转自: http://www.cnblogs.com/HondaHsu/archive/2008/12/01/1345372.html
查询计划及主要统计数据如下:
[align=left] 执行计划:[/align]
[align=left] -----------------------------------------[/align]
[align=left] ……[/align]
[align=left] 2 1 HASH JOIN (Cost=5 Card=14 Bytes=224)[/align]
[align=left] 3 2 TABLE ACCESS (FULL) OF 'DEPT' (Cost=2 Card=4 Bytes=52)[/align]
[align=left] 4 2 TABLE ACCESS (FULL) OF 'EMP' (Cost=2 Card=14 Bytes=42)[/align]
[align=left] 主要统计数据:[/align]
[align=left] -----------------------------------------[/align]
[align=left] 305 recursive calls[/align]
[align=left] 46 consistent gets[/align]
[align=left] 创建物化视图EMP_DEPT:[/align]
[align=left] create materialized view emp_dept build immediate[/align]
[align=left] refresh on demand[/align]
[align=left] enable query rewrite[/align]
[align=left] as[/align]
[align=left] select dept.deptno,dept.dname,count(*)[/align]
[align=left] from emp,dept[/align]
[align=left] where emp.deptno=dept.deptno[/align]
[align=left] group by dept.deptno,dept.dname[/align]
[align=left] /[/align]
[align=left] 再次执行查询,执行计划及主要统计数据如下:[/align]
[align=left] 执行计划:[/align]
[align=left] -------------------------------------[/align]
[align=left] ……[/align]
[align=left] 1 0 TABLE ACCESS (FULL) OF 'EMP_DEPT' (Cost=2 Card=327 Bytes=11445)[/align]
[align=left] 主要统计数据:[/align]
[align=left] ------------------------------------[/align]
[align=left] 79 recursive calls[/align]
[align=left] 28 consistent gets[/align]
可见,在建立物化视图之前,首先执行两个表的全表扫描,然后进行HASH连接,再进行分组排序和选择操作;而建立物化视图后,CBO自动将上述复杂操作转换为对物化视图EMP_DEPT的全扫描,相关的统计数据也有了很大的改善,递归调用(RECURSIVE CALLS)由305降到79,逻辑I/O(CONSISTENT GETS)由46降为28。
[align=left]4.2.3 将频繁访问的小表读入CACHE[/align]
逻辑I/O总是快于物理I/O。如果数据库中存在被应用程序频繁访问的小表,可将这些表强行读入KEEP池,从而避免物理I/O的发生。
[align=left]4.3.1 消除外部连接[/align]
通过消除外部连接,不仅使得到的查询更易于读取,而且性能也经常可以得到改善。一般的思路是,有以下形式的查询:
[align=left] SELECT …,OUTER_JOINED_TABLE.COLUMN[/align]
[align=left] FROM SOME_TABLE,OUTER_JOINED_TO_TABLE[/align]
[align=left] WHERE …=OUTER_JOINED_TO_TABLE(+)[/align]
[align=left] 可转换为如下形式的查询:[/align]
SELECT …,(SELECT COLUMN FROM OUTER_ JOINED_TO_TABLE WHERE …)FROM SOME_TABLE;
[align=left]4.3.2 谓词前推,优化中间结果[/align]
多表连接的性能低下多数是因为连接操作与过滤操作的次序不合理,大多数用户在编写多表连接查询时,总是先进行连接操作再应用过滤条件,这导致服务器做了太多的无用功。针对这类问题,其优化思路就是尽可能将过滤谓词前推,使不符合条件的记录提前被筛选掉,只对符合条件的少数记录进行连接处理,这样可成倍的提高SQL查询效能。
如下图所示的星形模型,现要统计最近三个月进货的商品在各种销售渠道上的销售业绩。
[align=center]图2 产品销售的星形模型[/align]
[align=left] 标准连接查询如下:[/align]
[align=left] Select a.prod_name,sum(b.sale_quant),[/align]
[align=left] sum(c.sale_quant),sum(d.sale_quant)[/align]
[align=left] From product a,tele_sale b,online_sale c,store_sale d[/align]
[align=left] Where a.prod_id=b.prod_id and a.prod_id=c.prod_id [/align]
[align=left] and a.prod_id=d.prod_id And a.order_date>sysdate-90[/align]
[align=left] Group by a.prod_id;[/align]
[align=left] 启用内嵌视图,且将条件a.order_date>sysdate-90前移,优化后代码如下:[/align]
Select a.prod_name,b.tele_sale_sum,c.online_sale_sum,d.store_sale_sum From product a,
(select sum(sal_quant) tele_sale_sum from product,tele_sale
Where product.order_date>sysdate-90 and product.prod_id =tele_sale.prod_id) b,
(select sum(sal_quant) online_sale_sum
from product,tele_sale
Where product.order_date>sysdate-90 and product.prod_id =online_sale.prod_id) c,
(select sum(sal_quant) store_sale_sum
from product,store_sale
Where product.order_date>sysdate-90 and product.prod_id =store_sale.prod_id) d,
[align=left] Where a.prod_id=b.prod_id and [/align]
[align=left] a.prod_id=c.prod_id and a.prod_id=d.prod_id;[/align]
查询计划及主要统计数据如下:
[align=left] 执行计划:[/align]
[align=left] -----------------------------------------[/align]
[align=left] ……[/align]
[align=left] 2 1 HASH JOIN (Cost=5 Card=14 Bytes=224)[/align]
[align=left] 3 2 TABLE ACCESS (FULL) OF 'DEPT' (Cost=2 Card=4 Bytes=52)[/align]
[align=left] 4 2 TABLE ACCESS (FULL) OF 'EMP' (Cost=2 Card=14 Bytes=42)[/align]
[align=left] 主要统计数据:[/align]
[align=left] -----------------------------------------[/align]
[align=left] 305 recursive calls[/align]
[align=left] 46 consistent gets[/align]
[align=left] 创建物化视图EMP_DEPT:[/align]
[align=left] create materialized view emp_dept build immediate[/align]
[align=left] refresh on demand[/align]
[align=left] enable query rewrite[/align]
[align=left] as[/align]
[align=left] select dept.deptno,dept.dname,count(*)[/align]
[align=left] from emp,dept[/align]
[align=left] where emp.deptno=dept.deptno[/align]
[align=left] group by dept.deptno,dept.dname[/align]
[align=left] /[/align]
[align=left] 再次执行查询,执行计划及主要统计数据如下:[/align]
[align=left] 执行计划:[/align]
[align=left] -------------------------------------[/align]
[align=left] ……[/align]
[align=left] 1 0 TABLE ACCESS (FULL) OF 'EMP_DEPT' (Cost=2 Card=327 Bytes=11445)[/align]
[align=left] 主要统计数据:[/align]
[align=left] ------------------------------------[/align]
[align=left] 79 recursive calls[/align]
[align=left] 28 consistent gets[/align]
可见,在建立物化视图之前,首先执行两个表的全表扫描,然后进行HASH连接,再进行分组排序和选择操作;而建立物化视图后,CBO自动将上述复杂操作转换为对物化视图EMP_DEPT的全扫描,相关的统计数据也有了很大的改善,递归调用(RECURSIVE CALLS)由305降到79,逻辑I/O(CONSISTENT GETS)由46降为28。
[align=left]4.2.3 将频繁访问的小表读入CACHE[/align]
逻辑I/O总是快于物理I/O。如果数据库中存在被应用程序频繁访问的小表,可将这些表强行读入KEEP池,从而避免物理I/O的发生。
4.3 多表连接优化
最能体现查询复杂性的就是多表连接,多表连接操作往往要耗费大量的CPU时间和内存,因此多表连接查询性能优化往往是SQL优化的重点与难点。[align=left]4.3.1 消除外部连接[/align]
通过消除外部连接,不仅使得到的查询更易于读取,而且性能也经常可以得到改善。一般的思路是,有以下形式的查询:
[align=left] SELECT …,OUTER_JOINED_TABLE.COLUMN[/align]
[align=left] FROM SOME_TABLE,OUTER_JOINED_TO_TABLE[/align]
[align=left] WHERE …=OUTER_JOINED_TO_TABLE(+)[/align]
[align=left] 可转换为如下形式的查询:[/align]
SELECT …,(SELECT COLUMN FROM OUTER_ JOINED_TO_TABLE WHERE …)FROM SOME_TABLE;
[align=left]4.3.2 谓词前推,优化中间结果[/align]
多表连接的性能低下多数是因为连接操作与过滤操作的次序不合理,大多数用户在编写多表连接查询时,总是先进行连接操作再应用过滤条件,这导致服务器做了太多的无用功。针对这类问题,其优化思路就是尽可能将过滤谓词前推,使不符合条件的记录提前被筛选掉,只对符合条件的少数记录进行连接处理,这样可成倍的提高SQL查询效能。
如下图所示的星形模型,现要统计最近三个月进货的商品在各种销售渠道上的销售业绩。
[align=center]图2 产品销售的星形模型[/align]
[align=left] 标准连接查询如下:[/align]
[align=left] Select a.prod_name,sum(b.sale_quant),[/align]
[align=left] sum(c.sale_quant),sum(d.sale_quant)[/align]
[align=left] From product a,tele_sale b,online_sale c,store_sale d[/align]
[align=left] Where a.prod_id=b.prod_id and a.prod_id=c.prod_id [/align]
[align=left] and a.prod_id=d.prod_id And a.order_date>sysdate-90[/align]
[align=left] Group by a.prod_id;[/align]
[align=left] 启用内嵌视图,且将条件a.order_date>sysdate-90前移,优化后代码如下:[/align]
Select a.prod_name,b.tele_sale_sum,c.online_sale_sum,d.store_sale_sum From product a,
(select sum(sal_quant) tele_sale_sum from product,tele_sale
Where product.order_date>sysdate-90 and product.prod_id =tele_sale.prod_id) b,
(select sum(sal_quant) online_sale_sum
from product,tele_sale
Where product.order_date>sysdate-90 and product.prod_id =online_sale.prod_id) c,
(select sum(sal_quant) store_sale_sum
from product,store_sale
Where product.order_date>sysdate-90 and product.prod_id =store_sale.prod_id) d,
[align=left] Where a.prod_id=b.prod_id and [/align]
[align=left] a.prod_id=c.prod_id and a.prod_id=d.prod_id;[/align]
相关文章推荐
- Oracle优化-SQL查询优化研究
- [转载] ORACLE中SQL查询优化研究
- ORACLE中SQL查询优化研究
- 解析Oracle数据扫描 Oracle SQL查询优化 引导局部范围数据扫描的方法(2)
- 解析Oracle数据扫描 Oracle SQL查询优化 引导局部范围数据扫描的方法(6)
- Oracle SQL 查询优化.Part4
- 解析Oracle数据扫描 Oracle SQL查询优化 引导局部范围数据扫描的方法(3)
- Oracle SQL 查询优化.Part1
- oracle 查询优化及sql改写
- Oracle SQL查询优化方法
- oracle中sql语句查询优化(一)
- Oracle SQL查询优化3.优化原则
- oracle中sql语句查询优化(二)
- 解析Oracle数据扫描 Oracle SQL查询优化 引导局部范围数据扫描的方法(4)
- Oracle SQL查询优化方法2
- 解析Oracle数据扫描 Oracle SQL查询优化 数据读取方式
- Oracle sql"NOT IN"语句优化,查询A表有、B表没有的数据
- ORACLE 性能优化-查询数据库慢SQL(其实还是awr和ash报告更方便~)
- oracle中sql语句查询优化(三)
- oracle查询优化之sql语句优化