博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Oracle优化-SQL查询优化研究

Posted on 2008-12-01 23:56  徐正柱-  阅读(435)  评论(0编辑  收藏  举报
查询计划及主要统计数据如下:
    执行计划:
    -----------------------------------------
    ……
       2    1   HASH JOIN (Cost=5 Card=14 Bytes=224)
       3    2   TABLE ACCESS (FULL) OF 'DEPT' (Cost=2 Card=4 Bytes=52)
       4    2   TABLE ACCESS (FULL) OF 'EMP' (Cost=2 Card=14 Bytes=42)
    主要统计数据:
    -----------------------------------------
        305  recursive calls
          46  consistent gets
    创建物化视图EMP_DEPT:
    create materialized view emp_dept build immediate
    refresh on demand
    enable query rewrite
    as
    select dept.deptno,dept.dname,count(*)
    from emp,dept
    where emp.deptno=dept.deptno
    group by dept.deptno,dept.dname
    /
    再次执行查询,执行计划及主要统计数据如下:
    执行计划:
    -------------------------------------
    ……
       1    0   TABLE ACCESS (FULL) OF 'EMP_DEPT' (Cost=2 Card=327 Bytes=11445)
    主要统计数据:
    ------------------------------------
         79  recursive calls
         28  consistent gets
    可见,在建立物化视图之前,首先执行两个表的全表扫描,然后进行HASH连接,再进行分组排序和选择操作;而建立物化视图后,CBO自动将上述复杂操作转换为对物化视图EMP_DEPT的全扫描,相关的统计数据也有了很大的改善,递归调用(RECURSIVE CALLS)由305降到79,逻辑I/O(CONSISTENT GETS)由46降为28。
4.2.3  将频繁访问的小表读入CACHE
    逻辑I/O总是快于物理I/O。如果数据库中存在被应用程序频繁访问的小表,可将这些表强行读入KEEP池,从而避免物理I/O的发生。

4.3  多表连接优化

    最能体现查询复杂性的就是多表连接,多表连接操作往往要耗费大量的CPU时间和内存,因此多表连接查询性能优化往往是SQL优化的重点与难点。
4.3.1  消除外部连接
    通过消除外部连接,不仅使得到的查询更易于读取,而且性能也经常可以得到改善。一般的思路是,有以下形式的查询:
    SELECT …,OUTER_JOINED_TABLE.COLUMN
    FROM SOME_TABLE,OUTER_JOINED_TO_TABLE
    WHERE …=OUTER_JOINED_TO_TABLE(+)
    可转换为如下形式的查询:
    SELECT …,(SELECT COLUMN FROM OUTER_ JOINED_TO_TABLE WHERE …)FROM SOME_TABLE;
4.3.2  谓词前推,优化中间结果
    多表连接的性能低下多数是因为连接操作与过滤操作的次序不合理,大多数用户在编写多表连接查询时,总是先进行连接操作再应用过滤条件,这导致服务器做了太多的无用功。针对这类问题,其优化思路就是尽可能将过滤谓词前推,使不符合条件的记录提前被筛选掉,只对符合条件的少数记录进行连接处理,这样可成倍的提高SQL查询效能。
    如下图所示的星形模型,现要统计最近三个月进货的商品在各种销售渠道上的销售业绩。
图2  产品销售的星形模型
    标准连接查询如下:
    Select a.prod_name,sum(b.sale_quant),
    sum(c.sale_quant),sum(d.sale_quant)
    From product a,tele_sale b,online_sale c,store_sale d
    Where a.prod_id=b.prod_id and a.prod_id=c.prod_id
    and a.prod_id=d.prod_id And a.order_date>sysdate-90
    Group by a.prod_id;
    启用内嵌视图,且将条件a.order_date>sysdate-90前移,优化后代码如下:
    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,
    Where a.prod_id=b.prod_id and
    a.prod_id=c.prod_id and a.prod_id=d.prod_id;