您的位置:首页 > 数据库

Postgresql null值判断,排序,以及排序后对索引的影响

2018-01-15 14:53 337 查看
首先null值不会分配空间,这一点与''是本质区别,但是表现形式是一样的

首先null值与任何值做布尔运算,结果都是false

null值判断,is null,is not null

hank=> create table tab1 (a int ,b varchar(20));

CREATE TABLE

hank=> insert into tab1 values(1,'hank');

INSERT 0 1

hank=> insert into tab1 values(1,null);  

INSERT 0 1

hank=> insert into tab1 values(1,'askasdjk');

INSERT 0 1

hank=> select * from tab1 where b <>'hank';

 a |    b     

---+----------

 1 | askasdjk

(1 row)

可见b为null的值是不被筛选的

hank=> insert into tab1 values(1,'');        

INSERT 0 1

hank=> select * from tab1 where b <>'hank';  

 a |    b     

---+----------

 1 | askasdjk

 1 | 

 ''是可以被筛选的

要想达到效果,可以用如下写法

select * from tab1 where b <>'hank' or b is null;

 a |    b     

---+----------

 1 | 

 1 | askasdjk

 1 | 

(3 rows)

hank=> select * from tab1 where coalesce(b,'0')<>'hank';

 a |    b     

---+----------

 1 | 

 1 | askasdjk

 1 | 

(3 rows)

null值排序

hank=>  select ctid,* from tab1 where b <>'hank' or b is null order by b nulls first;

 ctid  | a |    b     

-------+---+----------

 (0,2) | 1 | 

 (0,4) | 1 | 

 (0,3) | 1 | askasdjk

 hank=> select ctid,* from tab1 where b <>'hank' or b is null order by b nulls last; 

 ctid  | a |    b     

-------+---+----------

 (0,4) | 1 | 

 (0,3) | 1 | askasdjk

 (0,2) | 1 | 

(3 rows)

null值排序对索引的影响

null列索引注意一定要一致,否则索引用不到

insert into tab1 select generate_series(1,1000),'hank'||generate_series(1,1000);

hank=> create index idx_tab1_b on tab1(b nulls first);

hank=> explain select * from tab1  order by b limit 1; 

                             QUERY PLAN                              

---------------------------------------------------------------------

 Limit  (cost=21.06..21.06 rows=1 width=11)

   ->  Sort  (cost=21.06..23.57 rows=1004 width=11)

         Sort Key: b

         ->  Seq Scan on tab1  (cost=0.00..16.04 rows=1004 width=11)

(4 rows)

hank=> explain select * from tab1  order by b nulls first limit 1;    

                                    QUERY PLAN                                    

----------------------------------------------------------------------------------

 Limit  (cost=0.28..0.32 rows=1 width=11)

   ->  Index Scan using idx_tab1_b on tab1  (cost=0.28..49.21 rows=1004 width=11)

hank=> explain select * from tab1  order by b nulls last limit 1;     

                             QUERY PLAN                              

---------------------------------------------------------------------

 Limit  (cost=21.06..21.06 rows=1 width=11)

   ->  Sort  (cost=21.06..23.57 rows=1004 width=11)

         Sort Key: b

         ->  Seq Scan on tab1  (cost=0.00..16.04 rows=1004 width=11)

(4 rows)

可见,null值得先后可以决定索引是否可以用到idx_tab1_b这个索引,需要重新排序

hank=> create index idx_tab1_b_1 on tab1(b);    

CREATE INDEX

hank=>  explain select * from tab1 order by b;

                                  QUERY PLAN                                  

------------------------------------------------------------------------------

 Index Scan using idx_tab1_b_1 on tab1  (cost=0.28..49.21 rows=1004 width=11)

(1 row)

hank=>  explain select * from tab1 order by b desc;

                                      QUERY PLAN                                       

---------------------------------------------------------------------------------------

 Index Scan Backward using idx_tab1_b_1 on tab1  (cost=0.28..49.21 rows=1004 width=11)

(1 row)

hank=>  explain select * from tab1 order by b asc; 

                                  QUERY PLAN                                  

------------------------------------------------------------------------------

 Index Scan using idx_tab1_b_1 on tab1  (cost=0.28..49.21 rows=1004 width=11)

(1 row)

不涉及null值排序的索引不会出现此种情况

所以有空值的字段如果对null值有排序需求,那么建索引的时候一定要按筛选条件建立。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: