索引与Null值对于Hints及执行计划的影响

由于B*Tree索引不存储Null值,所以在索引字段允许为空的情况下,某些Oracle查询不会使用索引.

很多时候,我们看似可以使用全索引扫描(Full Index Scan)的情况,可能Oracle就会因为Null值的存在而放弃索引.

在此情况下即使使用Hints,Oracle也不会使用索引,其根本原因就是因为Null值的存在.

我们看以下测试.

username字段为Not Null时,Index Hints可以生效.

SQL> create table t as select username,password from dba_users;
Table created.
SQL> desc t
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 USERNAME                                  NOT NULL VARCHAR2(30)
 PASSWORD                                           VARCHAR2(30)
SQL> create index i_t on t(username);
Index created.
SQL> set autotrace trace explain
SQL> select * from t where username='EYGLE';
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |    34 |     2   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T    |     1 |    34 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("USERNAME"='EYGLE')
Note
-----
   - dynamic sampling used for this statement
SQL> set linesize 120
SQL> select /*+ index(t,i_t) */ * from t where username='EYGLE';
Execution Plan
----------------------------------------------------------
Plan hash value: 2928007915
------------------------------------------------------------------------------------
| Id  | Operation                   | Name | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |      |     1 |    34 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T    |     1 |    34 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | I_T  |     1 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("USERNAME"='EYGLE')
Note
-----
   - dynamic sampling used for this statement

当索引字段允许为Null时,Oracle放弃此索引:

SQL> alter table t modify (username null);
Table altered.
SQL> select /*+ index(t,i_t) */ * from t;
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    27 |   918 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| T    |    27 |   918 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------
Note
-----
   - dynamic sampling used for this statement 

当该字段为Not Null时,索引可以被强制使用:

SQL> alter table t modify (username not null);
Table altered.
SQL> select /*+ index(t,i_t) */ * from t;
Execution Plan
----------------------------------------------------------
Plan hash value: 3593393735
------------------------------------------------------------------------------------
| Id  | Operation                   | Name | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |      |    27 |   918 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T    |    27 |   918 |     2   (0)| 00:00:01 |
|   2 |   INDEX FULL SCAN           | I_T  |    27 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------
Note
-----
   - dynamic sampling used for this statement
 

这就是Null值对于索引及查询的影响.

OceanBase 数据库在优化器方面与 MySQL 数据库的区别,主要表现在以下几个方面: 1. 查看执行计划的命令 1)输出的列信息仅包含 ID、OPERATOR、NAME、EST. ROWS 和 COST 以及算子的详细信息。 2)不支持使用 SHOW WARNINGS 显示额外的信息。 2. 查看统计信息 1)支持执行 ANALYZE TABLE 语句查询数据字典表存储有关列的直方图统计信息。 2)支持通过内部表 __all_meta_table 查看表统计信息和列统计信息。 3. 查询改写优化 1)支持外联接优化 2)支持外联接简化 3)支持块嵌套循环和批量 Key 访问联接 4)支持条件过滤 5)支持常量叠算优化 6)支持 IS NULL 优化 (索引不存储 NULL ) 7)支持 ORDER BY 优化 8)支持 GROUP BY 优化 9)支持 DISTINCT 消除 10)支持 LIMIT 下压 11)支持 Window 函数优化 12)支持避免全表扫描 13)支持谓词下压 4. Optimizer Hint 机制 1)支持联接顺序 Optimizer Hints 2)支持表级别的 Optimizer Hints 3)支持索引级别的 Optimizer Hints 4)语法支持 INDEX Hint、FULL Hint、ORDERED Hint 和 LEADING Hint 等,不支持 USE INDEX 和 FORCE INDEX。 5. 兼容 MySQL 数据库的并行执行能力包括并行查询、并行复制和并行写入等,且 OceanBase 数据库已经支持并行算子,包括并行聚集、并行联接、并行分组以及并行排序等。 6. OceanBase 数据库还支持计划缓存和预编译,MySQL 数据库并不支持。 以上是OceanBase与mysql的优化器区别,仿造该格式列出postgresql与mysql的优化器区别
最新发布
07-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值