验证索引列NULL不走索引

今天遇到问题,同事问我,order by 主键列 desc 与order by 日期列(加了索引) desc ,怎么执行时间差距这么大;于是查看执行计划不一样:
order by 主键列 desc 对应 INDEX FULL SCAN DESCENDING
order by 日期列(加了索引) desc 对应 TABLE ACCESS FUL
我加hint /*+ index(table index_name) */ 强制使用索引,计划还是使用的全表扫描,很奇怪为什么没有使用索引呢?我加了hint就不应该是数据问题了吧。
最后明白了原因:主键 not null而日期列可为null,如果将日期列改为not null,执行计划会一致。

总结:Oracle可能因为索引字段列可以为Null而放弃使用索引。以下为INDEX FULL SCAN

SQL> create table null_valid(id int primary key,sid int null,sdate date); Table created. SQL> alter table null_valid drop column sdate; Table altered. SQL> desc dba_objects Name Null? Type ----------------------------------------- -------- ---------------------------- OWNER VARCHAR2(30) OBJECT_NAME VARCHAR2(128) SUBOBJECT_NAME VARCHAR2(30) OBJECT_ID NUMBER DATA_OBJECT_ID NUMBER OBJECT_TYPE VARCHAR2(19) CREATED DATE LAST_DDL_TIME DATE TIMESTAMP VARCHAR2(19) STATUS VARCHAR2(7) TEMPORARY VARCHAR2(1) GENERATED VARCHAR2(1) SECONDARY VARCHAR2(1) SQL> insert into null_valid select object_id,object_id from dba_objects where rownum < 100; 99 rows created. SQL> create index idx_sid on null_valid(sid); Index created. SQL> set autot trace explain SQL> select * from null_valid order by id desc; Execution Plan ---------------------------------------------------------- Plan hash value: 1230549944 -------------------------------------------------------------------------------- - | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------- - | 0 | SELECT STATEMENT | | 99 | 2574 | 4 (25)| 00:00:01 | | 1 | SORT ORDER BY | | 99 | 2574 | 4 (25)| 00:00:01 | | 2 | TABLE ACCESS FULL| NULL_VALID | 99 | 2574 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------------- - Note ----- - dynamic sampling used for this statement SQL> exec dbms_stats.gather_table_stats(user,'NULL_VALID'); PL/SQL procedure successfully completed. SQL> select * from null_valid order by id desc; Execution Plan ---------------------------------------------------------- Plan hash value: 600338710 -------------------------------------------------------------------------------- ----------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------- ----------- | 0 | SELECT STATEMENT | | 99 | 594 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| NULL_VALID | 99 | 594 | 2 (0)| 00:00:01 | | 2 | INDEX FULL SCAN DESCENDING| SYS_C005257 | 99 | | 1 (0)| 00:00:01 | -------------------------------------------------------------------------------- ----------- SQL> select * from null_valid order by sid desc; Execution Plan ---------------------------------------------------------- Plan hash value: 1230549944 -------------------------------------------------------------------------------- - | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------- - | 0 | SELECT STATEMENT | | 99 | 594 | 4 (25)| 00:00:01 | | 1 | SORT ORDER BY | | 99 | 594 | 4 (25)| 00:00:01 | | 2 | TABLE ACCESS FULL| NULL_VALID | 99 | 594 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------------- - SQL> select /*+ index(null_valid idx_sid) */ * from null_valid order by sid desc; Execution Plan ---------------------------------------------------------- Plan hash value: 1230549944 -------------------------------------------------------------------------------- - | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------- - | 0 | SELECT STATEMENT | | 99 | 594 | 4 (25)| 00:00:01 | | 1 | SORT ORDER BY | | 99 | 594 | 4 (25)| 00:00:01 | | 2 | TABLE ACCESS FULL| NULL_VALID | 99 | 594 | 3 (0)| 00:00:01 | --------------------------------------------------------------------------------以上sid字段(可以为null)加了索引,使用hint强制使用索引,计划依然使用全表扫描。

SQL> alter table null_valid modify sid not null; Table altered. SQL> select * from null_valid order by sid desc; Execution Plan ---------------------------------------------------------- Plan hash value: 2266710330 -------------------------------------------------------------------------------- ---------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------------- ---------- | 0 | SELECT STATEMENT | | 99 | 594 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| NULL_VALID | 99 | 594 | 2 (0)| 00:00:01 | | 2 | INDEX FULL SCAN DESCENDING| IDX_SID | 99 | | 1 (0)| 00:00:01 | --------------------------------------------------------------------------------以上将sid列改为not null,计划选择使用了INDEX FULL SCAN DESCENDING。

SQL> set linesize 120 SQL> alter table null_valid modify sid null; Table altered. SQL> select * from null_valid order by sid desc; Execution Plan ---------------------------------------------------------- Plan hash value: 1230549944 --------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 99 | 594 | 4 (25)| 00:00:01 | | 1 | SORT ORDER BY | | 99 | 594 | 4 (25)| 00:00:01 | | 2 | TABLE ACCESS FULL| NULL_VALID | 99 | 594 | 3 (0)| 00:00:01 | --------------------------------------------------------------------------------- SQL> select * from null_valid where sid is not null order by sid desc; Execution Plan ---------------------------------------------------------- Plan hash value: 2266710330 ------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 99 | 594 | 2 (0)| 00:00:01 | | 1 | TABLE ACCESS BY INDEX ROWID| NULL_VALID | 99 | 594 | 2 (0)| 00:00:01 | |* 2 | INDEX FULL SCAN DESCENDING| IDX_SID | 99 | | 1 (0)| 00:00:01 | ------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 2 - filter("SID" IS NOT NULL)
以上将sid字段重新改为null,在sql索引字段上添加 is not null WHERE条件,计划选择INDEX FULL SCAN DESCENDING。


总结:索引列为null在有些情况下会影响oracle选择使用该索引,而选择使用全表扫描。在很多情况下应该注意null。




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值