阳光网驿-企业信息化交流平台【DTC零售连锁全渠道解决方案】

 找回密码
 注册

QQ登录

只需一步,快速开始

扫描二维码登录本站

手机号码,快捷登录

老司机
查看: 1113|回复: 0

[转帖] sql查询中尽量减少的使用

[复制链接]
  • TA的每日心情
    开心
    2012-3-7 10:15
  • 签到天数: 11 天

    [LV.3]偶尔看看II

    发表于 2012-1-7 14:13:50 | 显示全部楼层 |阅读模式
    在数据库中抓到了下面的sql,每小时执行6次,查询条件中大部分是status字段,我推断应该是监控程序,每10分钟运行一次。监控程序一般都是提取异常数据,数据量很少,要不然监控就失去意义了,像这种sql一般是要通过索引迅速定位到数据的。
    原始sql:
    SQL> select  *
      2    from tc_xx_trade t
      3   where t.xx_status <> 4
      4     and t.xx_status <> 5
      5     and t.cs_status = 1
      6     and t.timeout_type <> 'STOP_TIMEOUT'
      7     and t.gmt_xiaoer_inter is not null
      8     and t.gmt_xiaoer_inter < sysdate
      9     and rownum < 50;

    Execution Plan
    --------------------------------------------------
    SELECT STATEMENT Optimizer=CHOOSE (Cost=9655 Card=49 Bytes=15092)
      COUNT (STOPKEY)
        TABLE ACCESS (FULL) OF 'TC_xx_TRADE' (Cost=9655 Card
    =263124 Bytes=81042192)

    Statistics
    ----------------------------------------------------------
              1  recursive calls
              1  db block gets
         109922  consistent gets
         101640  physical reads
            120  redo size
           5552  bytes sent via SQL*Net to client
            656  bytes received via SQL*Net from client
              2  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
              9  rows processed

    sql走全表扫描,根据上面的判断我认为cs_status=1的数据量应该很小,走索引会很快。

    加上hint:   
    SQL> select/*+index(t IDX_TC_REF_TRA_GMT_XIAOER)*/  *
      2    from tc_xx_trade t
      3   where t.xx_status <> 4
      4     and t.xx_status <> 5
      5     and t.cs_status = 1
      6     and t.timeout_type <> 'STOP_TIMEOUT'
      7     and t.gmt_xiaoer_inter is not null
      8     and t.gmt_xiaoer_inter < sysdate
      9     and rownum < 50;

    Execution Plan
    ---------------------------------------------------
       SELECT STATEMENT Optimizer=CHOOSE (Cost=113996 Card=49 Bytes   =15092)
    0   COUNT (STOPKEY)
    1     TABLE ACCESS (BY INDEX ROWID) OF 'TC_xx_TRADE' (Cost
       =113996 Card=263208 Bytes=81068064)
    2       INDEX (RANGE SCAN) OF 'IDX_TC_REF_TRA_GMT_XIAOER' (NON
       -UNIQUE) (Cost=32246 Card=273964)

    Statistics
    ----------------------------------------------------------
              0  recursive calls
              0  db block gets
          61745  consistent gets
          34586  physical reads
          65124  redo size
          11553  bytes sent via SQL*Net to client
            667  bytes received via SQL*Net from client
              3  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
             28  rows processed

    逻辑读还是很大,这表示cs_status=1的数据量应该是很多的,过滤性很差。
    监控一般只会取很少的一部分数据,哪个条件具有过滤性呢,不了解业务的情况下我们只能去推测,把xx_status<>转换为 in()试试看。
    <>转化为in:
    SQL> select *
      2    from tc_xx_trade t
      3    where t.xx_status in (1, 2, 3, 6)
      4     and t.cs_status = 1
      5     and t.timeout_type <> 'STOP_TIMEOUT'
      6     and t.gmt_xiaoer_inter is not null
      7     and t.gmt_xiaoer_inter < sysdate
      8     and rownum < 50;

    Execution Plan
    ----------------------------------------------------------
       SELECT STATEMENT Optimizer=CHOOSE (Cost=541550 Card=49 Bytes =15092)
    0   COUNT (STOPKEY)
    1     INLIST ITERATOR
    2       TABLE ACCESS (BY INDEX ROWID) OF 'TC_xx_TRADE' (Co
       st=541550 Card=1462696 Bytes=450510368)
    3         INDEX (RANGE SCAN) OF 'IDX_TC_REF_TRA_GMT_XIAOER' (N
       ON-UNIQUE) (Cost=4475 Card=1462696)

    Statistics
    ----------------------------------------------------------
              0  recursive calls
              0  db block gets
             898  consistent gets
              0   physical reads
              0  redo size
          15366  bytes sent via SQL*Net to client
            689  bytes received via SQL*Net from client
              5  SQL*Net roundtrips to/from client
              0  sorts (memory)
              0  sorts (disk)
             49  rows processed

    把<>转化成in字段,效果好了很多,原理我就不多解释了,实际上和用<>不走索引,会去扫描整个表是一样的道理。




    楼主热帖
    启用邀请码注册,提高发帖质量,建设交流社区
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    快速回复 返回顶部 返回列表