使用sample优化SQL

开发同学想使用以下的SQL随机取出状态为0的一条CODE用于业务上发奖品ID,但又事先不知道这个code,只能从这个cord表中找状态为0的记录。
select *
  from bb.b_card
 where code in (select code
                  from (select *
                          from bb.b_card
                         where rownum = 10
                         and status = 0
                           and expire_date >
                               to_date('2015-08-20', 'yyyy-mm-dd hh24:mi:ss')
                         order by dbms_random.random)
                 where rownum = 1);
执行计划如下:
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 754878421
---------------------------------------------------------------------------------------------
| Id  | Operation                    | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |              |     1 |    70 |  1619   (7)| 00:00:20 |
|   1 |  NESTED LOOPS                |              |     1 |    70 |  1619   (7)| 00:00:20 |
|   2 |   VIEW                       | VW_NSO_1     |     1 |    27 |  1618   (7)| 00:00:20 |
|*  3 |    COUNT STOPKEY             |              |       |       |            |          |
|   4 |     VIEW                     |              |   986K|    15M|  1618   (7)| 00:00:20 |
|*  5 |      SORT ORDER BY STOPKEY   |              |   986K|    40M|  1618   (7)| 00:00:20 |
|   6 |       COUNT                  |              |       |       |            |          |
|*  7 |        FILTER                |              |       |       |            |          |
|*  8 |         TABLE ACCESS FULL    | NOVICE_CARD  |   986K|    40M|  1618   (7)| 00:00:20 |
|   9 |   TABLE ACCESS BY INDEX ROWID| NOVICE_CARD  |   986K|    40M|     1   (0)| 00:00:01 |
|* 10 |    INDEX UNIQUE SCAN         | SYS_C0062248 |     1 |       |     1   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------
   3 - filter(ROWNUM=1)
   5 - filter(ROWNUM=1)
   7 - filter(ROWNUM=10)
   8 - filter("STATUS"=0 AND "EXPIRE_DATE">TO_DATE('2015-08-20','yyyy-mm-dd
              hh24:mi:ss'))
  10 - access("CODE"="$nso_col_1")
可以看到由于无法使用索引,这条SQL使用的是TABLE ACCESS FULL,后期如果随着表数据量的上升,此SQL会越来越慢。
我的优化如下:
select code
  from bb.bb_card sample(1)
 where rownum < 2
   and status = 0 and expire_date >to_date('2015-08-20', 'yyyy-mm-dd hh24:mi:ss');
执行计划如下:
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
Plan hash value: 1489415315
------------------------------------------------------------------------------------
| Id  | Operation            | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |             |     1 |    38 |     2   (0)| 00:00:01 |
|*  1 |  COUNT STOPKEY       |             |       |       |            |          |
|*  2 |   TABLE ACCESS SAMPLE| NOVICE_CARD |     1 |    38 |     2   (0)| 00:00:01 |
------------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------


   1 - filter(ROWNUM<2)
   2 - filter("STATUS"=0 AND "EXPIRE_DATE">TO_DATE('2015-08-20','yyyy-mm-dd
              hh24:mi:ss'))
这里使用到了Oracle 的sample随机取样,使用sample选项的意思是指定Oracle从表中随机选择记录样本,这样比从整个表中选择更高效。
sample(1)是指Oracle从表中读取特定百分比的记录(1%),并判断是否满足WHERE子句以返回结果。
优化完成后执行时间从4.17秒降低到0.015毫秒。


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26390465/viewspace-1777450/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/26390465/viewspace-1777450/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值