时间:2021-07-01 10:21:17 帮助过:2人阅读
for i in 1..9999 loop
insert into n1 values(i,‘name‘||i);
if mod(i,100)=0then
commit;
end if;
end loop;
insert into n1(sid)values(10000);
commit;
end;
查询sname列值走的是索引范围扫描
SQL> explain plan for select * from n1 where sname = 'name1';
Explained.
SQL> select * from table(dbms_xplan.display);
Plan hash value: 3644017351
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
|
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 75 | 2 (0)| 00:00:01
|
|* 1 | INDEX RANGE SCAN| N1_SNAME_IND | 1 | 75 | 2 (0)| 00:00:01
|
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("SNAME"='name1')
Note
-----
- dynamic sampling used for this statement (level=2)
is null方式查询,虽然sname中为null的记录1W行中只有一行,但还是没有走索引,也就是说is null不走索引。
SQL> explain plan for select * from n1 where sname is null;
Explained.
SQL> select * from table(dbms_xplan.display);
Plan hash value: 2416923229
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 75 | 9 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| N1 | 1 | 75 | 9 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("SNAME" IS NULL)
Note
-----
- dynamic sampling used for this statement (level=2)
17 rows selected.
如果实际情况确实需要is null查询走索引呢?可通过创建联合索引的方式来实现。
drop index n1_sname ;
create index n1_sname_ind on n1(sname,sid);
SQL> explain plan for select * from n1 where sid is not null and sname is null ;
SQL> select * from table(dbms_xplan.display);
Plan hash value: 3644017351
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
|
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 75 | 3 (0)| 00:00:01
|
|* 1 | INDEX RANGE SCAN| N1_SNAME_IND | 1 | 75 | 3 (0)| 00:00:01
|
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("SNAME" IS NULL)
filter("SID" IS NOT NULL)
Note
-----
- dynamic sampling used for this statement (level=2)
18 rows selected.
可以看到创建联合索引后,SQL查询所耗费的资源明显降低。
需要注意的是我们查询最频繁最经常使用列,比如sname要放在联合索引的第一列;同时要走联合索引,需要where后面的条件出现联合索引包含的所有的字段,这也是为什么加了sid这个字段的原因。
版权声明:本文为博主原创文章,未经博主允许不得转载。
SQL中的null
标签: