关于rownum的一个小实验

以前一直有个疑惑,例如sql:select * from test where object_name='YANG' and rownum=1;
那么该sql是把所有的object_name='YANG'全部都找出来显示一行给我呢,还是只找到一行了就停止再找?
话不多说,做个小实验:


1.构造一张表
create table test as select * from dba_objects;

2.将表的第一行作个更改
update test set object_name='YANG' where object_id=20;
commit;

3.查询object_name='YANG'的总行数
select count(*) from test where object_name='YANG';
这个就不贴了,肯定是1行

4.查看该sql的执行计划和统计信息
set autot trace exp stat
select * from test where object_name='YANG' and rownum=1;
(注意将以上sql多执行几次,让统计信息准确)

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |   207 |    36   (0)| 00:00:01 |
|*  1 |  COUNT STOPKEY     |      |       |       |            |          |
|*  2 |   TABLE ACCESS FULL| TEST |    20 |  4140 |    36   (0)| 00:00:01 |
---------------------------------------------------------------------------

   1 - filter(ROWNUM=1)
   2 - filter("OBJECT_NAME"='YANG')

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          4  consistent gets
          0  physical reads
          0  redo size
       1604  bytes sent via SQL*Net to client
        523  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
发现只有四个逻辑读

5.将表的最后一行作个更改(表的第一行和最后一行可以根据rowid进行选择)
update test set object_name='YANG' where object_id=88611;
commit;

6.查询object_name='YANG'的总行数
select count(*) from test where object_name='YANG';
这个就不贴了,肯定是2行

7.将以下sql执行一次,查看该sql的执行计划和统计信息
select * from test where object_name='YANG' and rownum=1;
发现跟第4步没什么区别,逻辑读都为4。那也就是说这次虽说有两行object_name='YANG',而且处于表的一头一尾,但是数据库只扫描到第一个满足条件的就退出了,所以说rownum=1的话,数据库只找到一行了就停止再找。

8.继续验证自己的结论
select * from test where object_name='YANG' and rownum<3;
---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     2 |   414 |    53   (0)| 00:00:01 |
|*  1 |  COUNT STOPKEY     |      |       |       |            |          |
|*  2 |   TABLE ACCESS FULL| TEST |    20 |  4140 |    53   (0)| 00:00:01 |
---------------------------------------------------------------------------

   1 - filter(ROWNUM<3)
   2 - filter("OBJECT_NAME"='YANG')

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
       1248  consistent gets
          0  physical reads
          0  redo size
       1729  bytes sent via SQL*Net to client
        523  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          2  rows processed
可以看到该sql为了找到2行,对表进行了个全扫描,对应的逻辑读也到了1248个,所以此刻更加肯定了在第七步中的结论。

后记:有些时候,我们都会被一些很莫名其妙的思路困扰,别担心,做个小实验就行了。

猜你喜欢

转载自www.cnblogs.com/ddzj01/p/9028217.html