对于整数大于3和大于等于4是否一样(二)

本文通过实验对比了在Oracle数据库中使用大于3和大于等于4作为WHERE条件时的索引扫描差异,证实了两种情况下的执行计划和性能表现相同。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://yangtingkun.itpub.net/post/468/474904



今天同事问了我一个问题,对于一个NUMBER(1)的列,查询中的WHERE条件如果分别是大于3和大于等于4,二者是否等价。

对于整数大于3和大于等于4是否一样:http://yangtingkun.itpub.net/post/468/474742

这里继续讨论二者在索引扫描上的区别。


昨天和同事讨论这个问题,同事认为如果是大于3的话,走索引扫描,会从3开始扫描,而大于等于4,会从4开始扫描,下面我们来验证一下这个观点是否正确。

根据这个观点对于大于3的情况,Oracle会先找到索引键值为3的块,然后开始扫描。而对于大于等于4的情况,则会找到索引键值为4的块,然后执行扫描。如果表中包含大量索引键值为3的记录,这两个查询就可能存在性能上的差异。

看一个具体的例子:

SQL> CREATE TABLE T_NUM (ID NUMBER, NAME VARCHAR2(30));

表已创建。

SQL> CREATE INDEX IND_T_NUM_ID ON T_NUM (ID);

索引已创建。

SQL> INSERT INTO T_NUM SELECT 3, OBJECT_NAME FROM DBA_OBJECTS;

已创建54688行。

SQL> INSERT INTO T_NUM SELECT * FROM T_NUM;

已创建54688行。

SQL> INSERT INTO T_NUM SELECT * FROM T_NUM;

已创建109376行。

SQL> INSERT INTO T_NUM SELECT * FROM T_NUM;

已创建218752行。

SQL> COMMIT;

提交完成。

创建一张测试表,表中所有的ID都等于3,下面插入一条ID4记录:

SQL> INSERT INTO T_NUM VALUES (4, 'TEST');

已创建 1 行。

SQL> COMMIT;

提交完成。

下面执行查询语句:

SQL> SET AUTOT ON
SQL> SET TIMING ON
SQL> SELECT * FROM T_NUM WHERE ID > 3;

ID NAME
---------- ------------------------------
4 TEST

已用时间: 00: 00: 00.06

执行计划
----------------------------------------------------------
Plan hash value: 3388343191

--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T_NUM | 1 | 30 | 3 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IND_T_NUM_ID | 1 | | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------

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

2 - access("ID">3)

Note
-----
- dynamic sampling used for this statement

统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
4 consistent gets
0 physical reads
0 redo size
465 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

SQL> SELECT * FROM T_NUM WHERE ID >= 4;

ID NAME
---------- ------------------------------
4 TEST

已用时间: 00: 00: 00.06

执行计划
----------------------------------------------------------
Plan hash value: 3388343191

--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T_NUM | 1 | 30 | 3 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IND_T_NUM_ID | 1 | | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------

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

2 - access("ID">=4)

Note
-----
- dynamic sampling used for this statement

统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
4 consistent gets
0 physical reads
0 redo size
465 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

可以看到,无论是执行时间,还是逻辑读,两个SQL没有任何的差别。为了更好的证明Oracle并没有读取ID等于3的记录,执行下面的查询:

SQL> SELECT COUNT(*) FROM T_NUM WHERE ID = 3;

COUNT(*)
----------
437504

已用时间: 00: 00: 00.10

执行计划
----------------------------------------------------------
Plan hash value: 3557129504

--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 291 (1)| 00:00:04 |
| 1 | SORT AGGREGATE | | 1 | 13 | | |
|* 2 | INDEX FAST FULL SCAN| IND_T_NUM_ID | 406K| 5164K| 291 (1)| 00:00:04 |
--------------------------------------------------------------------------------------

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

2 - filter("ID"=3)

Note
-----
- dynamic sampling used for this statement

统计信息
----------------------------------------------------------
10 recursive calls
2 db block gets
2655 consistent gets
0 physical reads
93896 redo size
410 bytes sent via SQL*Net to client
385 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

其实看过Concept对索引结构有一定了解就知道,根据Oracle索引结构的特点,无论是大于3还是大于等于4,二者的查询是扫描的叶节点都是同一个,因此不会在这一点上不会存在性能的差别。



yangtingkun 发表于:2008.12.05 23:38 ::分类: ( ORACLE ) ::阅读:(1876次) :: 评论 (0)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值