一.唯一索引

唯一索引字面上理解就是在索引上增加唯一约束,不允许出现索引值相同的行,目前只有Btree索引可以声明唯一索引,唯一键会自动创建唯一索引。

测试表:

test=# create table tbl_unique_index(a int, b int);
CREATE TABLE

示例1.创建唯一索引,相等数据只允许插入一行,NULL除外,因为NULL不等于NULL。

test=# create unique index idx_unq_tbl_unique_index_a_b on tbl_unique_index using btree (a,b);
CREATE INDEX
test=# \d tbl_unique_index
Table "public.tbl_unique_index"
Column | Type | Modifiers
--------+---------+-----------
a | integer |
b | integer |
Indexes:
"idx_unq_tbl_unique_index_a_b" UNIQUE, btree (a, b)
test=# insert into tbl_unique_index values (1,1);
INSERT 0 1
test=# insert into tbl_unique_index values (1,1);
ERROR: duplicate key value violates unique constraint "idx_unq_tbl_unique_index_a_b"
DETAIL: Key (a, b)=(1, 1) already exists.
test=# insert into tbl_unique_index values (1);
INSERT 0 1
test=# insert into tbl_unique_index values (1);
INSERT 0 1
test=# insert into tbl_unique_index values (1);
INSERT 0 1

示例2.唯一键会自动创建唯一索引

test=# truncate table tbl_unique_index ;
TRUNCATE TABLE
test=# alter table tbl_unique_index add constraint pk_tbl_unique_index_a primary key(a);
ALTER TABLE
test=# alter table tbl_unique_index add constraint uk_tbl_unique_index_b unique(b);
ALTER TABLE
test=# \d tbl_unique_index
Table "public.tbl_unique_index"
Column | Type | Modifiers
--------+---------+-----------
a | integer | not null
b | integer |
Indexes:
"pk_tbl_unique_index_a" PRIMARY KEY, btree (a)
"idx_unq_tbl_unique_index_a_b" UNIQUE, btree (a, b)
"uk_tbl_unique_index_b" UNIQUE CONSTRAINT, btree (b)

二.表达式索引

除针对表的字段直接创建索引外,还可以对字段进行某种运算之后的结果创建索引。

测试表

test=# create table tbl_expression(a varchar(32), b varchar(32));
CREATE TABLE
test=# insert into tbl_expression select concat('test',x),concat('you',x) from generate_series(1,10000) x;
INSERT 0 10000

如果此时分别在a和b字段上各创建一个Btree索引,分别使用a和b字段查询时会进行索引扫描。

test=# create index idx_tbl_expression_a on tbl_expression using btree (a);
CREATE INDEX
test=# create index idx_tbl_expression_b on tbl_expression using btree (b);
CREATE INDEX
test=#
test=# explain analyze select * from tbl_expression where a = 'TEST';
QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------
-
Index Scan using idx_tbl_expression_a on tbl_expression (cost=0.29..8.30 rows=1 width=15) (actual time=0.130..0.130 rows=0 loops=1)
Index Cond: ((a)::text = 'TEST'::text)
Planning time: 0.667 ms
Execution time: 0.168 ms
(4 rows) test=# explain analyze select * from tbl_expression where b = 'you';
QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------
-
Index Scan using idx_tbl_expression_b on tbl_expression (cost=0.29..8.30 rows=1 width=15) (actual time=0.171..0.171 rows=0 loops=1)
Index Cond: ((b)::text = 'you'::text)
Planning time: 0.126 ms
Execution time: 0.206 ms
(4 rows)

但是下面的两种查询方式是不会进行索引扫描的

select * from tbl_expression where upper(a) = 'TEST';
select * from tbl_expression where (a || ' ' ||b) = 'test you';
test=# explain analyze select * from tbl_expression where upper(a) = 'TEST';
QUERY PLAN
------------------------------------------------------------------------------------------------------------
Seq Scan on tbl_expression (cost=0.00..166.00 rows=50 width=15) (actual time=5.957..5.957 rows=0 loops=1)
Filter: (upper((a)::text) = 'TEST'::text)
Rows Removed by Filter: 10000
Planning time: 0.140 ms
Execution time: 6.014 ms
(5 rows) test=#
test=# explain analyze select * from tbl_expression where (a || ' ' ||b) = 'test you';
QUERY PLAN
------------------------------------------------------------------------------------------------------------
Seq Scan on tbl_expression (cost=0.00..191.00 rows=50 width=15) (actual time=7.851..7.851 rows=0 loops=1)
Filter: ((((a)::text || ' '::text) || (b)::text) = 'test you'::text)
Rows Removed by Filter: 10000
Planning time: 0.114 ms
Execution time: 7.883 ms
(5 rows)

此时就可以使用表达式创建索引来解决此类全表扫描问题。

test=# explain analyze select * from tbl_expression where upper(a) = 'TEST';
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on tbl_expression (cost=4.67..21.42 rows=50 width=15) (actual time=0.133..0.133 rows=0 loops=1)
Recheck Cond: (upper((a)::text) = 'TEST'::text)
-> Bitmap Index Scan on idx_tbl_expression_upper_a (cost=0.00..4.66 rows=50 width=0) (actual time=0.129..0.129 rows=0 loops=1)
Index Cond: (upper((a)::text) = 'TEST'::text)
Planning time: 0.565 ms
Execution time: 0.175 ms
(6 rows)
test=# create index idx_tbl_expression_a_b on tbl_expression ((a||' '||b));
CREATE INDEX
test=# explain analyze select * from tbl_expression where (a || ' ' ||b) = 'test you';
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------
Bitmap Heap Scan on tbl_expression (cost=4.67..21.55 rows=50 width=15) (actual time=0.130..0.130 rows=0 loops=1)
Recheck Cond: ((((a)::text || ' '::text) || (b)::text) = 'test you'::text)
-> Bitmap Index Scan on idx_tbl_expression_a_b (cost=0.00..4.66 rows=50 width=0) (actual time=0.128..0.128 rows=0 loops=1)
Index Cond: ((((a)::text || ' '::text) || (b)::text) = 'test you'::text)
Planning time: 0.582 ms
Execution time: 0.187 ms
(6 rows)

但是还是需要根据实际业务情况仔细评估后决定采用何种索引,因为并不是索引越多越好。

三.部分索引

只在自己感兴趣的那部分数据上创建索引,而不是对每一行数据都创建索引,此种方式创建索引就需要使用WHERE条件了。

创建两个完全相同的表比较部分索引和全索引的区别。

测试表

test=# create table tbl_partial_index(id bigint,alarm_time timestamp without time zone,level varchar(12),alarm_desc varchar(100));
CREATE TABLE
test=# create table tbl_partial_index1(id bigint,alarm_time timestamp without time zone,level varchar(12),alarm_desc varchar(100));
CREATE TABLE

写入完全相同的数据

test=# insert into tbl_partial_index(id,alarm_time,level,alarm_desc) 
select generate_series(1,9000000),clock_timestamp()::timestamp without time zone,'green','正常';
INSERT 0 9000000
test=# insert into tbl_partial_index(id,alarm_time,level,alarm_desc)
select generate_series(9000000,9000100),clock_timestamp()::timestamp without time zone,'red','攻击';
INSERT 0 101
test=#
test=#
test=# insert into tbl_partial_index1(id,alarm_time,level,alarm_desc)
select generate_series(1,9000000),clock_timestamp()::timestamp without time zone,'green','正常';
INSERT 0 9000000
test=# insert into tbl_partial_index1(id,alarm_time,level,alarm_desc)
select generate_series(9000000,9000100),clock_timestamp()::timestamp without time zone,'red','攻击';
INSERT 0 101

示例1.在tbl_partial_index表字段level上创建索引

test=# create index idx_tbl_partial_index_level on tbl_partial_index using btree (level);
CREATE INDEX
Time: 31407.356 ms
test=#
test=# explain analyze select * from tbl_partial_index where level = 'red';
QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------
-------------
Index Scan using idx_tbl_partial_index_level on tbl_partial_index (cost=0.43..4.45 rows=1 width=29) (actual time=0.069..0.087 rows=
101 loops=1)
Index Cond: ((level)::text = 'red'::text)
Planning time: 0.268 ms
Execution time: 0.124 ms
(4 rows) Time: 23.460 ms
test=# select relname,pg_size_pretty(pg_relation_size(oid)) from pg_class where relname='idx_tbl_partial_index_level';
relname | pg_size_pretty
-----------------------------+----------------
idx_tbl_partial_index_level | 191 MB
(1 row) Time: 71.799 ms

示例2.在tbl_partial_index1表字段level等于red的行上创建索引

test=# create index idx_tbl_partial_index1_level on tbl_partial_index1(level) where level = 'red';
CREATE INDEX
Time: 5558.905 ms
test=# explain analyze select * from tbl_partial_index1 where level = 'red';
QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------
---------------
Index Scan using idx_tbl_partial_index1_level on tbl_partial_index1 (cost=0.14..4.16 rows=1 width=29) (actual time=0.051..0.082 row
s=101 loops=1)
Planning time: 18.922 ms
Execution time: 0.136 ms
(3 rows) Time: 19.929 ms
test=# select relname,pg_size_pretty(pg_relation_size(oid)) from pg_class where relname='idx_tbl_partial_index1_level';
relname | pg_size_pretty
------------------------------+----------------
idx_tbl_partial_index1_level | 64 kB
(1 row) Time: 0.950 ms

比较上面两个示例的结果可知,全表索引在耗时和大小方面要比部分索引消耗更多的资源,查询'red'的数据排除环境影响基本相同,数据量更大,'red'占比更小时性能可能会有明显差异,但是查询非'red'数据时全表索引会有明显的性能优势,因为部分索引并没有'green'数据的索引,走的是全表扫描。

综上,根据数据的使用方式创建不同的索引在性能上是有明显差异的。

postgresql----唯一索引,表达式索引,部分索引的更多相关文章

  1. 聚集索引、非聚集索引、聚集索引组织表、堆组织表、Mysql/PostgreSQL对比、联合主键/自增长、InnoDB/MyISAM(引擎方面另开一篇)

    参考了多篇文章,分别记录,如下. 下面是第一篇的总结 http://www.jb51.net/article/76007.htm: 在MySQL中,InnoDB引擎表是(聚集)索引组织表(cluste ...

  2. mysql索引之一:索引基础(B-Tree索引、哈希索引、聚簇索引、全文(Full-text)索引区别)(唯一索引、最左前缀索引、前缀索引、多列索引)

    没有索引时mysql是如何查询到数据的 索引对查询的速度有着至关重要的影响,理解索引也是进行数据库性能调优的起点.考虑如下情况,假设数据库中一个表有10^6条记录,DBMS的页面大小为4K,并存储10 ...

  3. PostgreSQL 11 新特性之覆盖索引(Covering Index)(转载)

    通常来说,索引可以用于提高查询的速度.通过索引,可以快速访问表中的指定数据,避免了表上的扫描.有时候,索引不仅仅能够用于定位表中的数据.某些查询可能只需要访问索引的数据,就能够获取所需要的结果,而不需 ...

  4. Mysql索引介绍及常见索引(主键索引、唯一索引、普通索引、全文索引、组合索引)的区别

    Mysql索引概念:说说Mysql索引,看到一个很少比如:索引就好比一本书的目录,它会让你更快的找到内容,显然目录(索引)并不是越多越好,假如这本书1000页,有500也是目录,它当然效率低,目录是要 ...

  5. SQL Server索引 - 聚集索引、非聚集索引、非聚集唯一索引 <第八篇>

    聚集索引.非聚集索引.非聚集唯一索引 我们都知道建立适当的索引能够提高查询速度,优化查询.先说明一下,无论是聚集索引还是非聚集索引都是B树结构. 聚集索引默认与主键相匹配,在设置主键时,SQL Ser ...

  6. MySQL5.7 虚拟列实现表达式或函数索引

    MySQL5.7 虚拟列实现表达式或函数索引 http://www.linuxidc.com/Linux/2015-11/125162.htm https://dev.mysql.com/doc/re ...

  7. SQL有三个类型的索引,唯一索引 不能有重复,但聚集索引,非聚集索引可以有重复

    重要: (1) SQL如果创建时候,不指定类型那么默认是非聚集索引 (2) 聚集索引和非聚集索引都可以有重复记录,唯一索引不能有重复记录. (3) 主键 默认是加了唯一约束的聚集索引,但是也可以在主键 ...

  8. SQL存储原理及聚集索引、非聚集索引、唯一索引、主键约束的关系(补)

    索引类型 1.          唯一索引:唯一索引不允许两行具有相同的索引值 2.          主键索引:为表定义一个主键将自动创建主键索引,主键索引是唯一索引的特殊类型.主键索引要求主键中的 ...

  9. Mysql使用Java UUID作为唯一值时使用前缀索引测试

    Mysql可以使用字符串前缀 作为索引 以节约空间. 下面我们以 Java的UUID 生成的 32位(移除UUID中的 中划线)字符串 来做一下 测试. 表结构: CREATE TABLE `test ...

  10. 认识SQLServer索引以及单列索引和多列索引的不同

     一.索引的概念 索引的用途:我们对数据查询及处理速度已成为衡量应用系统成败的标准,而采用索引来加快数据处理速度通常是最普遍采用的优化方法. 索引是什么:数据库中的索引类似于一本书的目录,在一本书中使 ...

随机推荐

  1. Stay hungry, stay foolish. 求知若饥,虚心若愚。

    如果留意我博客的朋友,应该都有看到这句话在我的自我介绍栏目存在了好长一段时间了,另外,我的 QQ.旺旺.MSN等都有这个签名.Stay hungry, stay foolish.(求知若饥,虚心若愚) ...

  2. 关于Unity中的光照(一)

    一.光源定义 光源,是一个普通节点加一个Light组件,创建的时候可以直接创建光源节点,也可以先创建一个空节点,再添加Light组件实例. 二.颜色形成 看到的物体颜色受两个很重要的因素的影响,一个是 ...

  3. selenium测试(Java)-- 验证信息(八)

    package com.test.validationinfor; import org.openqa.selenium.WebDriver; import org.openqa.selenium.f ...

  4. C# VS本地Sqlserver 操作笔记

    1.如何连接本地数据库 -- string Info = @"Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirecto ...

  5. windows 解压缩命令

    首先安装winrar 压缩: 命令:start winrar a test test.py 解压: 命令:start winrar x -y test.rar F:\batShell\test\tes ...

  6. webBrowser1.Document.Cookie取不到HttpOnly的Cookie,取Cookie不完整【转】

    在做数据采集时,有些网站需要输入验证码,但各网站验证码都不同,不可能有完美的识别验证码的代码,所以我也没去研究,我所采取的方案是:在winform里通过WebBrowser调用网页先手动登录系统,然后 ...

  7. 双卡手机怎么指定SIM卡打电话

    双卡手机如何指定SIM卡打电话 package com.example.dualsimtest; import android.app.Activity; import android.content ...

  8. C# 延时小函数 很好用

    平时我们在做winform开发的时候,有时候需要让程序休眠几秒钟,但是,如果我们直接使用 thread.sleep()函数,页面ui就会停止响应.怎么样解决呢,你可以把页面涉及到表现ui的代码放到一个 ...

  9. 【Java集合的详细研究2】浅谈Arrays.asList的使用

    首先,该方法是将数组转化为list.有以下几点需要注意: (1)该方法不适用于基本数据类型(byte,short,int,long,float,double,boolean) (2)该方法将数组与列表 ...

  10. hdu5087——Revenge of LIS II

    Revenge of LIS II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...