0


【postgresql初级使用】创建不同索引类型,选择适合数据类型的索引,查看执行计划,评估不同索引路径的性能

索引的使用

专栏内容

  • postgresql使用入门基础
  • 手写数据库toadb
  • 并发编程

个人主页:我的主页
管理社区:开源数据库
座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.

文章目录

概述


在postgresql中内置了丰富的索引类型如btree, hash, gin, gist, sp-gist,还有扩展的bloom等等索引,同时还可以有不同的用途,如主键,外键,唯一性等。

本文分享如何使用不同类型的索引,如创建,查看,删除;同时通过查看执行计划,了解查询状态与索引使用情况,最后通过案例如果分析增加适合自己的索引。

索引


在《postgresql 基础入门》专栏中分享了创建默认类型索引的SQL语法,这里主要介绍创建不同类型索引的语法,同时分享查看索引,删除索引的语法。

创建索引

创建索引的语法如下:

createindex index_name ON tablename using index_type ( column1 );

其中:

  • index_name,本次创建的索引名称,长度在64个字符以内;
  • ON关键字之后是表名tablename,在此表的某一列上创建索引,指定列名为 column1;
  • using关键字指示使用的索引算法类型,可以使用btree,hash等内置的索引类型;

下面我们在

product

表的上创建hash索引。

表的定义如下:

-- 创建产品表  CREATETABLE products (  
    product_id INTPRIMARYKEY,  
    product_name VARCHAR(255)NOTNULL,  
    price DECIMAL(10,2)NOTNULL,  
    category VARCHAR(255));

可以插入几条数据,也可以使用前面章节《物化视图》提到的方法初始化大量数据来对比。

这里已经有了很多数据,先打开客户端的执行时间统计功能,查询名称wfplpgsbre为的商品。

postgres=# \timing on
Timing ison.
postgres=# select * from products where product_name='wfplpgsbre';
 product_id | product_name | price  | category
------------+--------------+--------+-----------44| wfplpgsbre   |199.66| Category4
(1row)Time: 4.828 ms

然后在商品名称列上创建hash类型的索引。

postgres=# create index idx_pro_name ON products using hash ( product_name );CREATEINDEXTime: 64.740 ms

这里我们对比一下增加索引后的查询效果。

postgres=# select * from products where product_name='wfplpgsbre';
 product_id | product_name | price  | category
------------+--------------+--------+-----------44| wfplpgsbre   |199.66| Category4
(1row)Time: 0.279 ms

可以看到增加索引后,查询明显变快了,效果提升了20倍。

查看索引

在postgresql的命令行客户端上,可以用以下几种方法来查看。

  • 使用psql客户端的\di命令
postgres=>\di
                   List of relations
  Schema  |     Name      | Type  |  Owner   |  Table
----------+---------------+-------+----------+----------
 senlleng | idx_pro_name  | index | senllang | products
 senlleng | orders_pkey   | index | senllang | orders
 senlleng | products_pkey | index | senllang | products
(3 rows)postgres=>\di idx_pro_name
                   List of relations
  Schema  |     Name     | Type  |  Owner   |  Table
----------+--------------+-------+----------+----------
 senlleng | idx_pro_name | index | senllang | products
(1 row)
\di

命令是display index 缩写,如果不带索引名称,就会查询当前数据库中的所有索引,可以看到有主键索引,还有刚才创建的索引。
如果带索引名称,就会查看该索引的详细信息。

  • 另一种是查看表的定义,使用\d命令
postgres=>\d products
                       Table "senlleng.products"
    Column    |          Type          | Collation | Nullable | Default
--------------+------------------------+-----------+----------+---------
 product_id   | integer                || not null |
 product_name | character varying(255)|| not null |
 price        | numeric(10,2)|| not null |
 category     | character varying(255)|||
Indexes:
    "products_pkey" PRIMARY KEY, btree (product_id)"idx_pro_name"hash(product_name)
Referenced by:
    TABLE "orders" CONSTRAINT "orders_product_id_fkey" FOREIGN KEY (product_id) REFERENCES products(product_id)

在表的详细信息中,会列出表上的索引列表,可以看到products表中,有两个索引,分别是products_pkey和idx_pro_name。

删除索引

删除索引就比较简单,语法如下:

dropindex index_name;

删除上面创建的索引。

postgres=>dropindex idx_pro_name ;DROPINDEXTime: 9.890 ms

查看执行计划


索引经常用于提升SQL的查询性能,性能的优化是一个综合而复杂的事情,这里介绍一个常用的手段,就是查看执行计划。

执行计划是数据库将输入SQL命令解析之后,根据当前数据表的状态,如表中数据行的多少,被查询的列上是否有索引等等,对每一种路径都会统计其耗时,然后选出一个耗时较少的路径来最终执行,这就是执行计划。

当然生成执行计划的过程很复杂,但是我们可以查看执行计划,来评估执行的效率,决定是否需要增加索引来优化,以及使用那种类型索引更优秀。

查看执行计划,使用命令

explain

在执行SQL前加

explain

就会打印执行计划,查看一下查询产品的SQL。

postgres=>explainselect*from products where product_name='lrqfankmib';
                         QUERY PLAN------------------------------------------------------------
 Seq Scan on products  (cost=0.00..1992.00rows=1 width=31)
   Filter: ((product_name)::text='lrqfankmib'::text)(2rows)Time: 0.237 ms

这是索引已经删除的情况下,可以看到执行计划中

Seq Scan on products

,说明在这个张表上执行顺序扫描,也就是从头遍历查找,要把表整个遍历一次。

在数据量少时,顺序扫描还是可以接受的,在大数据分析场景下,那简直是灾难级的。

下面我们通过案例来看看,如何使用索引。

案例分析


顺序查找效率比较低时,我们给常用字段加一个索引。

添加默认索引类型

给产品名增加默认索引类型btree,来看看执行计划和性能的变化情况。

postgres=>createindex btree_proname on products usingbtree(product_name );CREATEINDEXTime: 122.786 ms

看一下执行计划。

postgres=>explainselect*from products where product_name ='lrqfankmib';
                                  QUERY PLAN-------------------------------------------------------------------------------Index Scan using btree_proname on products  (cost=0.42..8.44rows=1 width=31)Index Cond: ((product_name)::text='lrqfankmib'::text)(2rows)Time: 0.322 ms

可以看到用到了我们刚才创建的索引

Index Scan using btree_proname on products

下面实际再执行一遍,看一下耗时的变化。

postgres=>select*from products where product_name ='lrqfankmib';
 product_id | product_name | price  | category
------------+--------------+--------+-----------51| lrqfankmib   |254.70| Category2
(1row)Time: 0.242 ms

确实快了很多,到1ms以下了。

创建hash索引

按商品名称的特点,一般不会使用比较运算,符合hash算法的特点,我们在商品名上创建hash索引。

postgres=>createindex hash_proname on products usinghash( product_name);CREATEINDEXTime: 83.966 ms
postgres=> \d products
                       Table"senlleng.products"Column|Type| Collation | Nullable |Default--------------+------------------------+-----------+----------+---------
 product_id   |integer||notnull|
 product_name |charactervarying(255)||notnull|
 price        |numeric(10,2)||notnull|
 category     |charactervarying(255)|||
Indexes:
    "products_pkey"PRIMARYKEY,btree(product_id)"btree_proname"btree(product_name)"hash_proname"hash(product_name)
Referenced by:
    TABLE"orders"CONSTRAINT"orders_product_id_fkey"FOREIGNKEY(product_id)REFERENCES products(product_id)

可以看到创建hash索引之后,商品名上有两个索引,也就是说按索引执行的路径就有两种。

再来看一下执行计划吧。

postgres=>explainselect*from products where product_name ='lrqfankmib';
                                  QUERY PLAN------------------------------------------------------------------------------Index Scan using hash_proname on products  (cost=0.00..8.02rows=1 width=31)Index Cond: ((product_name)::text='lrqfankmib'::text)(2rows)Time: 0.286 ms

btree与hash索引比较

可以看到执行计划中使用了刚创建的hash索,也就是说经过postgresql 数据库的计算,还是使用hash索引耗时较短。

下面实际执行一下。

postgres=>select*from products where product_name ='lrqfankmib';
 product_id | product_name | price  | category
------------+--------------+--------+-----------51| lrqfankmib   |254.70| Category2
(1row)Time: 0.157 ms

可以看到,与btree索引差别非常小,在毫秒级,可能多次执行统计会更准确一些。

总结


本文介绍了在postgresql 中使用不同类型索引的方法,通过查看SQL的执行计划,来评估查询的性能,一般采用索引查询。当然不同数据类型,要采用对应的索引类型,会取得较好的效果,最后通过在商品名称上创建btree与hash索引,对应字符匹配hash索引更符合一些。

结尾


非常感谢大家的支持,在浏览的同时别忘了留下您宝贵的评论,如果觉得值得鼓励,请点赞,收藏,我会更加努力!

作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。

注:未经同意,不得转载!


本文转载自: https://blog.csdn.net/senllang/article/details/138798606
版权归原作者 韩楚风 所有, 如有侵权,请联系我们删除。

“【postgresql初级使用】创建不同索引类型,选择适合数据类型的索引,查看执行计划,评估不同索引路径的性能”的评论:

还没有评论