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

索引的使用

专栏内容

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

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

文章目录

  • 索引的使用
  • 概述
  • 索引
    • 创建索引
    • 查看索引
    • 删除索引
  • 查看执行计划
  • 案例分析
    • 添加默认索引类型
    • 创建hash索引
    • btree与hash索引比较
  • 总结
  • 结尾

概述


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

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

索引


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

创建索引

创建索引的语法如下:

create index index_name ON tablename using index_type ( column1 );

其中:

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

下面我们在product表的上创建hash索引。

表的定义如下:

-- 创建产品表  
CREATE TABLE products (  product_id INT PRIMARY KEY,  product_name VARCHAR(255) NOT NULL,  price DECIMAL(10, 2) NOT NULL,  category VARCHAR(255)  
);  

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

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

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

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

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

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

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

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

查看索引

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

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

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

  • 另一种是查看表的定义,使用\d命令
postgres=> \d productsTable "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。

删除索引

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

drop index index_name;

删除上面创建的索引。

postgres=> drop index idx_pro_name ;
DROP INDEX
Time: 9.890 ms

查看执行计划


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

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

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

查看执行计划,使用命令explain

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

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

这是索引已经删除的情况下,可以看到执行计划中Seq Scan on products,说明在这个张表上执行顺序扫描,也就是从头遍历查找,要把表整个遍历一次。

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

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

案例分析


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

添加默认索引类型

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

postgres=> create index btree_proname on products using btree (product_name );
CREATE INDEX
Time: 122.786 ms

看一下执行计划。

postgres=> explain select * from products where product_name = 'lrqfankmib';QUERY PLAN
-------------------------------------------------------------------------------Index Scan using btree_proname on products  (cost=0.42..8.44 rows=1 width=31)Index Cond: ((product_name)::text = 'lrqfankmib'::text)
(2 rows)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
(1 row)Time: 0.242 ms

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

创建hash索引

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

postgres=> create index hash_proname on products using hash ( product_name);
CREATE INDEX
Time: 83.966 ms
postgres=> \d productsTable "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)"btree_proname" btree (product_name)"hash_proname" hash (product_name)
Referenced by:TABLE "orders" CONSTRAINT "orders_product_id_fkey" FOREIGN KEY (product_id) REFERENCES products(product_id)

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

再来看一下执行计划吧。

postgres=> explain select * from products where product_name = 'lrqfankmib';QUERY PLAN
------------------------------------------------------------------------------Index Scan using hash_proname on products  (cost=0.00..8.02 rows=1 width=31)Index Cond: ((product_name)::text = 'lrqfankmib'::text)
(2 rows)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
(1 row)Time: 0.157 ms

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

总结


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

结尾


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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/11317.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

冯喜运:5.13黄金原油震荡整理是涨还是跌?今日走势分析

【黄金消息面分析】;自5月初以来,黄金和白银一直在享受需求的回归,买家在过去几天加大了力度,一度推动金价重返2370美元上方,白银重返28.5美元上方。不过,经过几天的盘整后,黄金白银价格双双下跌。然而&…

C# 中string和stringbuilder区别

在 C# 中,string 和 StringBuilder 是用于处理字符串的两种不同类型。它们之间的主要区别在于如何处理和操作字符串。 string: string 是不可变的,表示一个不可变的字符序列。一旦创建了一个 string 对象,它的值就不能被修改。任何对 string…

Redis-详解(基础)

文章目录 什么是Redis?用Redis的特点?用Redis可以实现哪些功能?Redis的常用数据类型有哪些?Redis的常用框架有哪些?本篇小结 更多相关内容可查看 什么是Redis? Redis(Remote DictionaryServer)是一个开源…

下载文件名称乱码或变成了随机码

如图 后端是有正常返回附件名称的,浏览器开发工具中也正常显示了这个数据,但是下载下来的文件名称确实一堆随机码. 其实这个问题的原因是因为跨域 查看console: Refused to get unsafe header "content-disposition" 现象,后端传递到前端的fileName不能被识别,下载…

大模型与AIGC应用相关问题 模型大型

最近经常被问,你看“万亿的模型都出来了,你们训练的千亿模型是不是落伍了?”我想说:“虽然都叫超大模型,但是类型是不一样的,虽说每一类模型训出来都不容易,不过澄清一下概念还是必要的”。 大…

java数据结构与算法(删除链表的倒数第N个节点)

前言 删除链表的倒数第N个节点,涉及倒数基本需要快慢指针。 实现原理 删除链表的倒数第N个节点可以通过使用双指针技巧来实现。具体步骤如下: 使用两个指针,让它们之间相隔 N 个节点。遍历链表,直到第一个指针到达链表末尾。此…

编写Ansible角色实现分布式LNMP安装

前言 本文将介绍如何使用 Ansible 编写角色,在分布式环境下完成 LNMP(Linux、Nginx、MySQL、PHP)的自动化(编译)安装和配置,并验证 PHP 与 MySQL 数据联通性,实现博客和论坛页面的展示。 常规…

Qt---信号和槽

一、信号和槽机制 所谓信号槽,实际就是观察者模式。当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。这种发出是没有目的的,类似广播。如果有对象对这个信号…

二叉树的四种遍历代码实现

二叉树的遍历大致能分为以下几种 1.前序:根 左 右 2.中序:左 根 右 3.后序:左 右 根 4.层序:从根开始一层一层的向下 如上图访问顺序: 前序:1 2 3 N N N 4 5 N N 6 N N 中序:N 3 N 2 N 1 N 5 N 4 N …

docker-compose安装emqx集群(最新)(host模式)

机器: 10.60.0.20 10.60.0.21 10.60.0.22 一、三台机子都配置域名(/etc/hosts) 10.60.0.20 node1.emqx.io 10.60.0.22 node3.emqx.io 10.60.0.21 node2.emqx.io 二、docker-compose.yml(10.60.0.21) 其他两台机子自…

接搭建仿美团、代付系统源码搭建教程

最近很多粉丝催更、分享一下地球号:xiaobao0214520(WX) 现在大家都很流行搞网恋,我们搭建一个跟美团相似的系统 然后开发一个好友代付,我们在点单的时候转发链接让网恋对象付钱 若只是单点外卖的话,能榨出的油水还是太少。 所以…

Golang — map的使用心得和底层原理

map作为一种基础的数据结构,在算法和项目中有着非常广泛的应用,以下是自己总结的map使用心得、实现原理、扩容机制和增删改查过程。 1.使用心得: 1.1 当map为nil和map为空时,增删改查操作时会出现的不同情况 我们可以发现&#…

【全开源】废品回收微信小程序基于FastAdmin+ThinkPHP+UniApp

介绍 一款基于FastAdminThinkPHPUniApp开发的废品回收系统,适用废品回收站、再生资源回收公司上门回收使用的小程序 功能特性 1、会员注册 支持小程序授权注册和手机号注册 2、回收品类 可设置回收品类,废纸、废金属、废玻璃、旧衣服等 3、今日指导价…

面试高频知识点:Java互联网大厂高频面试题(持续收录)

文章目录 前言一、Java基础题1、Java语言的三大特性2、JDK 和 JRE 有什么区别3、Java基本数据类型及其封装类4、说明一下public static void main(String args[])这段声明里关键字的作用5、java的数据结构有哪些?6、抽象类和接口的区别?7、 与 equals 的区别8、Str…

WordPress插件Show IDs by Echo,后台显示文章、页面、分类、标签、媒体库、评论、用户的ID

WordPress的这款Show IDs by Echo插件,可以让我们设置是增加一列ID还是直接在“编辑 |快速编辑 |查看”操作后面增加ID,而且支持展示以下内容的ID: 文章页面类别标签评论自定义帖子类型自定义分类法用户媒体 Show IDs by Echo插件的安装及启…

企业级OV SSL证书:强化在线信任与安全的权威之选

在数字经济浪潮下,企业网站的安全性直接影响着用户信任度和业务的可持续发展。其中,企业级组织验证(Organization Validation,简称OV)SSL证书作为安全解决方案的重要一环,以其独有的优势,在众多…

【LeetCode】每日一题:994.腐烂的橘子

在给定的 m x n 网格 grid 中,每个单元格可以有以下三个值之一: 值 0 代表空单元格; 值 1 代表新鲜橘子; 值 2 代表腐烂的橘子。 每分钟,腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。 返回 直到单元格中没有新…

网安面经之文件包含漏洞

一、文件包含漏洞 1、文件包含漏洞原理?危害?修复? 原理:开发⼈员⼀般希望代码更灵活,所以将被包含的⽂件设置为变量,⽤来进⾏动态调⽤,但是由于⽂件包含函数加载的参数没有经过过滤或者严格的…

LVDS 源同步接口

传统数据传输通常采用系统同步传输方式,多个器件基于同一时钟源进行系统同步,器件之间的数据传输时序关系以系统时钟为参考,如图1所示。系统同步传输方式使各器件处于同步工作模式,但器件之间传输数据的传输时延难以确定&#xff…

图解JVM出现的参数

参数说明-XX:UseParNewGC使用ParNew作为垃圾回收器-XX:HandlePromotionFailure设置如果老年代内存<新生代所有对象大小时要不要Full GC&#xff0c;如果没设置就要Fuul GC&#xff0c;设置了就不要Full GC&#xff0c;而是进一步检查。-Xmx, -Xms, -Xmn, -XX:PermSize, -XX:…