部分索引
概述
在通常创建的索引中,会覆盖一列的全部数据,而有些时候,访列的一部分数据经常被用到,而另一些数据几乎不会用到,如果全部数据都被索引引用,会造成索引数据占用空间比较大。
本文就来介绍postgresql 中的部分索引(partial index),使用它可以让自己关心的数据,或者热点数据独立创建索引,同时通过几个案例,来分享它的几种独特的用法。
部分索引的使用
本节分享部分索引(partial index)的语法,以及创建部分索引的演示。
语法介绍
部分索引的创建sql与普通索引类似,也可以使用using
子句选择索引类型,下面是创建部分索引的语法sql。
create index index_name
on tablename(column1, column2, ...)
where qual;
与普通索引不同的是,在索引定义最后增加where
子句,用于过滤创建索引的数据。
- 索引删除
索引删除语法与普通索引是一样的,可以参考前一章节《》。
创建部分索引
下面来演示一下创建部分索引。
还是用前面一节用的表结构,它的定义如下:
-- 创建产品表
create table products (
product_id int primary key,
product_name varchar(255) not null,
price decimal(10, 2) not null,
category varchar(255)
);
数据的批量生成与插入,参见前面章节《》中有详细说明,这里不再赘述。
我们创建其中一类商品的索引,因为这类商品是主销商品。
postgres=> create index pidx_cate6 on products (category ) where category='category6';
create index
time: 17.965 ms
此时创建了关于6号类型的商品的索引,下面我们看一下索引的使用情况,查看方法可以参考前一章节《》。
postgres=> select * from products where category ='category6' and product_name='pxyiitdjjo';
product_id | product_name | price | category
------------+--------------+--------+-----------
24 | pxyiitdjjo | 411.59 | category6
(1 row)
time: 1.964 ms
postgres=> explain select * from products where category ='category6' and product_name='pxyiitdjjo';
query plan
-----------------------------------------------------------------------------
bitmap heap scan on products (cost=93.05..981.35 rows=1 width=31)
recheck cond: ((category)::text = 'category6'::text)
filter: ((product_name)::text = 'pxyiitdjjo'::text)
-> bitmap index scan on pidx_cate6 (cost=0.00..93.05 rows=9753 width=0)
(4 rows)
time: 0.259 ms
查询一个类型6下面的商品,通过explain
查看它的执行计划,可以看到通过pidx_cate6
索此进行了最内层的过滤bitmap index scan on pidx_cate6
,用到了我们刚才创建的部分索引。
那我们再来看一下,如果查询一个类型7的商品,会不会使用索引呢?
postgres=> explain select * from products where category ='category7' and product_name='pxyiitdjjo';
query plan
----------------------------------------------------------------------------------------------------
seq scan on products (cost=0.00..2242.00 rows=1 width=31)
filter: (((category)::text = 'category7'::text) and ((product_name)::text = 'pxyiitdjjo'::text))
(2 rows)
time: 0.246 ms
正如我们所料,查询类型7中的商品,使用了顺序查找的方法,没有索引可用。
使用场景
部分索引在实际项目中还是非常有用的,下面我们来分享几种具体的应用场景。
用于有效数据
在一些管理系统中,经常会积累大量的历史数据,但是经常使用的都是最新数据。
比如员工信息管理系统中,经过几年的使用,其中员工信息表中有一部分离职员的信息,它不会从数据库中删除,但在业务流中几乎不再访问。随着企业的成长,这类数据占比会慢慢提高,严重影响对员工信息表的使用效率。
对于类似场景,就可以建立部分数据索引,只对有效数据,或者是关心的数据建立索引,可以大大提升数据使用的性能。
下面以员工信息来举例。
员工信息表定义
create table employee (
eid int primary key,
ename varchar(50) not null,
birth_date date,
position varchar(100),
department varchar(100) ,
email varchar(100) ,
phone_number varchar(20),
hire_date date ,
address varchar,
emergency_contact varchar(100),
isleave boolean
);
其中 isleave字段表示是否在职。
员工信息数据
postgres=> insert into employee values(1,'lihua','2010-10-1','jiangsu','sales department','abc','123','2015-4-22','jiangsu','34', false),(2,'zhanglei','2000-10-1','jiangsu','software department','df','444','2015-1-22','jiangsu','65645',true);
insert 0 2
time: 8.032 ms
postgres=> select * from employee ;
eid | ename | birth_date | position | department | email | phone_number | hire_date | address | emergency_contact | isleave
-----+----------+------------+----------+---------------------+-------+--------------+------------+---------+-------------------+---------
1 | lihua | 2010-10-01 | jiangsu | sales department | abc | 123 | 2015-04-22 | jiangsu | 34 | f
2 | zhanglei | 2000-10-01 | jiangsu | software department | df | 444 | 2015-01-22 | jiangsu | 65645 | t
(2 rows)
time: 0.172 ms
插入了两行数据,其中一人已经离职。
创建在职人员的索引
postgres=> create index pidx_isleave on employee (isleave ) where isleave=false;
create index
time: 8.087 ms
这样在查询在职人员时就可以使用部分索引进行优化,而不是全量的数据中查询。
用于唯一性索引
案例三,设置一个部分唯一性索引
对于一个结果表来说,成功分支只有一个,产生的结果最多也只有一个;还有一个部门的组织架构中,manager职位也是最多只有一个。
这些都可以使用部分索引特性,只在这些值的数据上创建唯一性索引,来约束它们,这样在数据的最底层就可以控制,而不是通过编写程序来校验。
下面我们来举一个结果表的例子。
结果表定义
create table tests (
subject text,
target text,
success boolean
);
其中结果字段success对应的内容为 subject和target。
在整个测试中,成功的分支只有一个,也就是对应的结果success=true只有一行数据,对应的subject和target也是唯一的。
创建唯一性索引
要保证唯一的条件时,当success为true时,subject与target也不能重复。
可以创建下面的唯一性索引来约束。
create unique index tests_success_constraint on tests (subject,
target)
where success;
当subject和target相同时,算作一个测试分支,此测试分支中结果为真数据最多只有一个。
总结
在本节中,主要测试了postgresql 中部分索引partial index的语法和创建,并演示了sql的使用。
同时也列举了一些部分索引的使用场景和案例,能帮助我们在数据库应用设计中,简化模型和提升性能。
结尾
作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。
注:未经同意,不得转载!
发表评论