nulls first & nulls last 对索引影响


-- 当我们需要排序字段时,比如order by name,如果name字段定义时没有not null时,就有可能涉及到null值的排序
-- 如果不注意,可能会造成隐藏的bug,pg默认null是无穷大,在升序时排在最后面,当然在排序时也可以指定 nulls first 或 nulls last
-- 具体使用方法在此不在复述,本文主要是讲的是在创建索引时指定 nulls first 或 nulls last 对查询的影响

-- 基础创建索引语法如下
CREATE INDEX [ ASC | DESC ] [ NULLS { FIRST | LAST } ]

-- 在升序或降序时的默认值
-- NULLS FIRST
Specifies that nulls sort before non-nulls. This is the default when DESC is specified.
-- NULLS LAST
Specifies that nulls sort after non-nulls. This is the default when DESC is not specified.

--创建测试表
create table t as select n id ,'rudy'||n as name ,n||'password' as password,now() + (n||' second')::interval as create_date from generate_seies(1,1000000) n;

postgres=# update t set name = null where mod(id,2)=0;
UPDATE 500000
-- 构造随机的null值,本次测试取对半
postgres=# create table t1 as select * from t;
SELECT 1000000
postgres=# create index on t(name);
CREATE INDEX
postgres=# create index on t1(name nulls first);
CREATE INDEX

-- 在不指定 null first 时,由于pg默认null无限大,故当排序为升序时,t表能够使用索引,t1表却是使用全表扫描
postgres=# explain verbose select * from t where id>1000 order by name limit 10;
                                        QUERY PLAN
-------------------------------------------------------------------------------------------
 Limit  (cost=0.42..1.26 rows=10 width=33)
   Output: id, name, password, create_date
   ->  Index Scan using idx_t_name on public.t  (cost=0.42..83387.28 rows=999027 width=33)
         Output: id, name, password, create_date
         Filter: (t.id > 1000)
(5 rows)

postgres=# explain verbose select * from t1 where id>1000 order by name limit 10;
                                  QUERY PLAN
-------------------------------------------------------------------------------
 Limit  (cost=40949.92..40949.94 rows=10 width=33)
   Output: id, name, password, create_date
   ->  Sort  (cost=40949.92..43447.52 rows=999041 width=33)
         Output: id, name, password, create_date
         Sort Key: t1.name
         ->  Seq Scan on public.t1  (cost=0.00..19361.00 rows=999041 width=33)
               Output: id, name, password, create_date
               Filter: (t1.id > 1000)
(8 rows)

-- 在指定 nulls first 时,由于t1表创建索引时null值放在最前面,而且排序字段为升序,所以t1表使用索引,t表使用全表扫描
postgres=# explain verbose select * from t where id>1000 order by name nulls first limit 10;
                                  QUERY PLAN
------------------------------------------------------------------------------
 Limit  (cost=46095.61..46095.64 rows=10 width=33)
   Output: id, name, password, create_date
   ->  Sort  (cost=46095.61..48593.18 rows=999027 width=33)
         Output: id, name, password, create_date
         Sort Key: t.name NULLS FIRST
         ->  Seq Scan on public.t  (cost=0.00..24507.00 rows=999027 width=33)
               Output: id, name, password, create_date
               Filter: (t.id > 1000)
(8 rows)

postgres=# explain verbose select * from t1 where id>1000 order by name nulls first limit 10;
                                         QUERY PLAN
---------------------------------------------------------------------------------------------
 Limit  (cost=0.42..0.98 rows=10 width=33)
   Output: id, name, password, create_date
   ->  Index Scan using t1_name_idx on public.t1  (cost=0.42..55921.45 rows=999041 width=33)
         Output: id, name, password, create_date
         Filter: (t1.id > 1000)
(5 rows)

-- 综上,为什么会出现这样的结果,因为我们默认创建的btree索引,其叶子结点的数据是有序排列的,当创建索引不指定nulls first时,pgl默认把null值放在叶子节点的最后
-- 如果排序时只是order by name,未指定nulls first,pg只需要根据索引顺序的返回需要的数据则可,否则,如果order by name nulls last,pg如果使用索引,
-- 其可能先在叶子未尾节点返回null值的数据,再在叶子起始节点开始返回数据(假设需要返回10条数据,null值为5条,非null值有5条),其明显此时使用索引不是高效的
时间: 2024-08-30 15:00:05

nulls first & nulls last 对索引影响的相关文章

PostgreSQL 数据库NULL值的默认排序行为与查询、索引定义规范 - nulls first\last, asc\desc

标签 PostgreSQL , NULLS FIRST , NULLS LAST , ASC , DESC , 默认行为 , sort 背景 在数据库中NULL值是指UNKNOWN的值,不存储任何值,在排序时,它排在有值的行前面还是后面通过语法来指定. 例如 -- 表示null排在有值行的前面 select * from tbl order by id nulls first; -- 表示null排在有值行的后面 select * from tbl order by id nulls last;

PostgreSQL NULL值相对位置与QUERY优化 - nulls first\last, asc\desc

标签 PostgreSQL , NULLS FIRST , NULLS LAST , ASC , DESC , 默认行为 , sort 背景 在数据库中NULL值是指UNKNOWN的值,不存储任何值,在排序时,它排在有值的行前面还是后面通过语法来指定. 例如 -- 表示null排在有值行的前面 select * from tbl order by id nulls first; -- 表示null排在有值行的后面 select * from tbl order by id nulls last;

索引对查询条件顺序的影响

索引|条件 原帖地址:http://community.csdn.net/expert/FAQ/FAQ_Manage.asp?id=0&Topicid=3390663 环境:Sql Server2000 +sp4 问题:select datediff(day,'20040910','20040920')  --这句可以执行 --而下面这句不能执行(有时也可以执行)--sub_para为varchar(8),错误信息是:从字符串转换为 datetime 时发生语法错误.select * from

浅析SQL Server 聚焦索引对非聚集索引的影响

前言 在学习SQL 2012基础教程过程中会时不时穿插其他内容来进行讲解,相信看过SQL Server 2012 T-SQL基础教程的童鞋知道前面写的所有内容并非都是摘抄书上内容,如若是这样那将没有任何意义,学习的过程必须同时也是一个思考的过程,无论是独立思考也好还是查资料也罢都是思考而非走马观花,要不然过一段时间又会健忘.简短的内容,深入的理解. 话题 非聚集索引定义:非聚集索引也是一个B树结构,与聚集索引不同的是,B树的叶子节点存的是指向堆或聚集索引的指针.你真的理解了吗??你能举出例子吗?

SQL Server-聚焦聚集索引对非聚集索引的影响(四)

前言 在学习SQL 2012基础教程过程中会时不时穿插其他内容来进行讲解,相信看过SQL Server 2012 T-SQL基础教程的童鞋知道前面写的所有内容并非都是摘抄书上内容,如若是这样那将没有任何意义,学习的过程必须同时也是一个思考的过程,无论是独立思考也好还是查资料也罢都是思考而非走马观花,要不然过一段时间又会健忘.简短的内容,深入的理解,Always to review the basics. 话题 非聚集索引定义:非聚集索引也是一个B树结构,与聚集索引不同的是,B树的叶子节点存的是指

PostgreSQL SQL 语言:索引

本文档为PostgreSQL 9.6.0文档,本转载已得到原译者彭煜玮授权. 1. 简介 假设我们有一个如下的表: CREATE TABLE test1 ( id integer, content varchar ); 而应用发出很多以下形式的查询: SELECT content FROM test1 WHERE id = constant; 在没有事前准备的情况下,系统不得不扫描整个test1表,一行一行地去找到所有匹配的项.如果test1中有很多行但是只有一小部分行(可能是0或者1)需要被该

SQL Server中索引使用及维护

server|索引 在应用系统中,尤其在联机事务处理系统中,对数据查询及处理速度已成为衡量应用系统成败的标准.而采用索引来加快数据处理速度也成为广大数据库用户所接受的优化方法. 在良好的数据库设计基础上,能有效地使用索引是SQL Server取得高性能的基础,SQL Server采用基于代价的优化模型,它对每一个提交的有关表的查询,决定是否使用索引或用哪一个索引.因为查询执行的大部分开销是磁盘I/O,使用索引 提高性能的一个主要目标是避免全表扫描,因为全表扫描需要从磁盘上读表的每一个数据页,如果

MySQL索引及查询优化总结 专题

  小结:db名与应用名相同,表名:业务名_此表的作用 ,表名表示内容,不体现数量,如果表示boolean概念,表名需要使用is_业务含义来表示,但POJO中不应该出现isXXX,因为不方便序列化,中间的对应关系,使用ResultMap来映射字段名中有多个单词,使用下划线连接,字段名不能以数字打着,数字和单词之间,只需要一个下划线,譬如xx_3xx,不建议写成xx_3_xx最左前缀原则    如果是联合索引,Btree索引在使用时受索引建立的字段顺序的影响where条件中有or,建议拆成unio

数据库查询优化——Mysql索引

版权声明:本文为博主原创文章,转载注明出处http://blog.csdn.net/u013142781 目录(?)[+] 工作一年了,也是第一次使用MySQL的索引.添加了索引之后的速度的提升,让我惊叹不已.隔壁的老员工看到我的大惊小怪,平淡地回了一句"那肯定啊". 对于任何DBMS,索引都是进行优化的最主要的因素.对于少量的数据,没有合适的索引影响不是很大,但是,当随着数据量的增加,性能会急剧下降. 小宝鸽试了一下,2.5万数据单表中,无索引:200ms-700ms,添加索引后10