今天做个有趣的实验。
/*********************postgresql 数据库测试开始*********************/
--本次测试以pg 数据库 10.11版本postgres=# select version();version-------------------------------------------------------------PostgreSQL 10.11, compiled by Visual C++ build 1800, 64-bit(1 行记录)
--创建一张测试表create table t_index_null(id varchar(50),name text);
--造测试数据insert into t_index_null(id,name)select t.id,'test'||t.id::varcharfrom (select generate_series as idfrom generate_series(1,100000) ) as t;
--添加一条 id为null的数据insert into t_index_null(name) values ('zqw01');
--添加一条 id为空字符的数据insert into t_index_null(id,name) values ('','zqw02');
--对 id列 创建索引create index idx_t_index_null_id on t_index_null(id);
--检锁id=1 的数据,看执行计划是否会走索引,执行计划走索引过滤explain analyzeselect id,namefrom t_index_nullwhere id = '1';QUERY PLAN-----------------------------------------------------------------------------------------------------------------------------------Index Scan using idx_t_index_null_id on t_index_null (cost=0.29..8.31 rows=1 width=14) (actual time=0.061..0.062 rows=1 loops=1)Index Cond: ((id)::text = '1'::text)Planning time: 0.289 msExecution time: 0.086 ms(4 行记录)
--检锁id='' (空字符) 的数据,看执行计划是否会走索引,执行计划走索引过滤explain analyzeselect id,namefrom t_index_nullwhere id = '';QUERY PLAN-----------------------------------------------------------------------------------------------------------------------------------Index Scan using idx_t_index_null_id on t_index_null (cost=0.29..8.31 rows=1 width=14) (actual time=0.050..0.052 rows=1 loops=1)Index Cond: ((id)::text = ''::text)Planning time: 0.114 msExecution time: 0.078 ms(4 行记录)
--检锁id is null (空字符) 的数据,看执行计划是否会走索引,执行计划走索引过滤explain analyzeselect id,namefrom t_index_nullwhere id is null;QUERY PLAN------------------------------------------------------------------------------------------------------------------------------------Index Scan using idx_t_index_null_id on t_index_null (cost=0.29..10.97 rows=3 width=14) (actual time=0.105..0.106 rows=1 loops=1)Index Cond: (id IS NULL)Planning time: 0.115 msExecution time: 0.133 ms(4 行记录)
/*********************postgresql 数据库测试结束*********************/
/*********************oracle 数据库测试开始*************************/
--本次测试以oracle 数据库 11.0版本SQL> select * from v$version;BANNER--------------------------------------------------------------------------------Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit ProductionPL/SQL Release 11.2.0.1.0 - ProductionCORE 11.2.0.1.0 ProductionTNS for Linux: Version 11.2.0.1.0 - ProductionNLSRTL Version 11.2.0.1.0 - Production
--创建一张测试表create table scott.t_index_null(id varchar2(50),name varchar2(4000));
--造测试数据insert into scott.t_index_null(id,name)select level,'test'||levelfrom dualconnect by level <= 100000;
--添加一条 id为null的数据insert into scott.t_index_null(name) values ('zqw01');
--添加一条 id为空字符的数据insert into scott.t_index_null(id,name) values ('','zqw02');
--对 id列 创建索引create index idx_t_index_null_id on scott.t_index_null(id);
--检锁id=1 的数据,看执行计划是否会走索引,执行计划走索引过滤set auto offexplain plan forselect id,namefrom scott.t_index_nullwhere id = '1';select * from table(dbms_xplan.display);PLAN_TABLE_OUTPUT--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------Plan hash value: 42603800---------------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |---------------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 2029 | 2 (0)| 00:00:01 || 1 | TABLE ACCESS BY INDEX ROWID| T_INDEX_NULL | 1 | 2029 | 2 (0)| 00:00:01 ||* 2 | INDEX RANGE SCAN | IDX_T_INDEX_NULL_ID | 1 | | 1 (0)| 00:00:01 |---------------------------------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------2 - access("ID"='1')Note------ dynamic sampling used for this statement (level=2)
--检锁id='' (空字符) 的数据,看执行计划是否会走索引,从下面的执行计划来看, id = ''过滤,并没有走索引扫描,而是走全表扫表set auto offexplain plan forselect id,namefrom scott.t_index_nullwhere id = '';select * from table(dbms_xplan.display);PLAN_TABLE_OUTPUT--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------Plan hash value: 1102671017-----------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |-----------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 2029 | 0 (0)| ||* 1 | FILTER | | | | | || 2 | TABLE ACCESS FULL| T_INDEX_NULL | 118K| 229M| 104 (2)| 00:00:02 |-----------------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------1 - filter(NULL IS NOT NULL)Note------ dynamic sampling used for this statement (level=2)
--检锁id is null (空字符) 的数据,看执行计划是否会走索引,从下面的执行计划来看,id is null 也是没有走索引扫描,而是走全表扫表set auto offexplain plan forselect id,namefrom scott.t_index_nullwhere id is null;select * from table(dbms_xplan.display);PLAN_TABLE_OUTPUT--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------Plan hash value: 1935092368----------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |----------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 4 | 8116 | 104 (2)| 00:00:02 ||* 1 | TABLE ACCESS FULL| T_INDEX_NULL | 4 | 8116 | 104 (2)| 00:00:02 |----------------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------1 - filter("ID" IS NULL)Note------ dynamic sampling used for this statement (level=2)
/*********************oracle 数据库测试结束*************************/
总结:
postgresql 数据库某一列如果存储空字符'', 或者存在null值,然后在对这一列加索引,如果SQL用到了 = '' 或者 is null 过滤,执行计划有可能会走索引;
Oracle 数据库某一列如果存储空字符'', 或者存在null值,然后对这一列加索引,如果SQL用到了 = '' 或者 is null 过滤,SQL执行计划是一定不会走索引扫描;
文章转载自朱清伟的学习笔记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




