【postgresql初级使用】在表的多个频繁使用列上创建一个索引,多条件查询优化,多场景案例揭示索引失效

多列索引

专栏内容

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

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

文章目录

  • 多列索引
  • 概述
  • 多列索引创建
    • 创建语法
    • 创建说明
  • 案例分析
    • 创建数据
    • 创建索引
    • 带首列查询
    • 不带首列查询
  • 总结
  • 结尾

概述


在实际业务的查询中,往往会带有多个过滤条件,涉及多个列,而索引也能够以多列数据构成。

在postgresql 中,一个索引可以由最多32个列来构建,如果业务中有多列查询情况,可以对此进行优化。

当然,多列索引在应用时,复杂度会提升,应用不当反尔性能下降。

本文就来分享一下多列索引的使用,同时通过案例来剖析它的原理,揭示它的优势与不足,避免遇坑。

多列索引创建


下面分享多列索引的创建语法,在postgresql中的限制说明。

创建语法

多列索引的创建SQL语法如下:

CREATE INDEX index_name
ON table_name(column1, column2, ...);

基本SQL形式与普通索引相同,只是在选择表的列时,可以指定为多列,这里最多为32个列。

创建说明

  • 支持的索引类型

当然也可以使用using子句指定索引类型,不指定时默认为btree类型。

在postgresql中,多列索引可以使用的索引类型有btree, brin, gin和gist,其它类型不支持。

  • 列的顺序

创建索引时,指定列的顺序是有讲究的,不然会事得其反。

where条件中,使用频繁程度高的列,要放在前面,依次排序。

比如 column1,column2,column3这样的顺序建索引时,那么对于

... where column1 = a;

... where column1 = a and column2 = b;

... where column1 = a and column2 = b and column3 = c;

这三种情况都可以用到该索引,其中column1的使用频率最高,column2次之,最后是column3。

  • 列的数量

虽然多列索引可以支持最大32列,通过实践证明,最多不要超过两到三列。

案例分析


通过对btree类型的多列索引进行分析,看看多列索引的运行机制。

创建数据

为了演示方便,我们创建如下数据表。

CREATE TABLE test1 (major int,minor int,last  int,name varchar);

往表中插入10万条测试数据。

postgres=> INSERT INTO test1(major,minor,last,name)
select id, (random() * 100000)::int, (random() * 100000 + 100)::int, 'name' || id::int FROM generate_series(1, 100000) as id;INSERT 0 100000

创建索引

在major, minor, last 三列数据上创建一个索引,操作如下:

postgres=> create index idx_test1 ON test1 (major ,minor, last);
CREATE INDEX
postgres=> \d test1Table "senlleng.test1"Column |       Type        | Collation | Nullable | Default
--------+-------------------+-----------+----------+---------major  | integer           |           |          |minor  | integer           |           |          |last   | integer           |           |          |name   | character varying |           |          |
Indexes:"idx_test1" btree (major, minor, last)

创建索引idx_test1,它是在三列上创建的默认btree索引,查看表定义,可以看到索引已经创建。

下面我们来看看如何使用此索引。

带首列查询

这里先来看看带有索引首列major带的条件查询,它可以分为以下情况:

  • 条件带有major, minor, last三列;
postgres=> explain select * from test1 where major = 1005 and minor > 5000 and last < 8000;QUERY PLAN
------------------------------------------------------------------------Index Scan using idx_test1 on test1  (cost=0.42..8.44 rows=1 width=21)Index Cond: ((major = 1005) AND (minor > 5000) AND (last < 8000))
(2 rows)

可以看到使用了刚才创建的索引 idx_test1,那么我们将条件中各列的顺序进行调换,再来看看。

postgres=> explain select * from test1 where last < 8000 and minor > 5000 and major = 1005 ;QUERY PLAN
------------------------------------------------------------------------Index Scan using idx_test1 on test1  (cost=0.42..8.44 rows=1 width=21)Index Cond: ((major = 1005) AND (minor > 5000) AND (last < 8000))
(2 rows)

同样也使用了索引,同时很惊奇的发现, Index Cond: ((major = 1005) AND (minor > 5000) AND (last < 8000)) 索引条件居然与我们where子句中的相反。

这一变动,其实由查询优化器来做的,它为什么这么做呢? 哎,看下面的案例分析就明白了。

  • 带major,另外两列之一;

如果减少其中一列,还会用到索引路径吗? 下面我们来看看还有第一列major,但是其它两列任选一列时,会是什么情况发生呢?

postgres=> explain select * from test1 where last < 8000  and major = 1005 ;QUERY PLAN
------------------------------------------------------------------------Index Scan using idx_test1 on test1  (cost=0.42..8.44 rows=1 width=21)Index Cond: ((major = 1005) AND (last < 8000))
(2 rows)postgres=> explain select * from test1 where  minor > 5000 and major = 1005 ;QUERY PLAN
------------------------------------------------------------------------Index Scan using idx_test1 on test1  (cost=0.42..8.44 rows=1 width=21)Index Cond: ((major = 1005) AND (minor > 5000))
(2 rows)

可以看到,索引仍然使用到了。

当然单独带有第一列时,也是同样可以使用索引的。

不带首列查询

如果不带第一列major时,又会是什么情况呢?

postgres=> explain select * from test1 where last < 8000 and minor > 5000 ;QUERY PLAN
------------------------------------------------------------Seq Scan on test1  (cost=0.00..2137.00 rows=7814 width=21)Filter: ((last < 8000) AND (minor > 5000))
(2 rows)postgres=> explain select * from test1 where minor > 5000 ;QUERY PLAN
-------------------------------------------------------------Seq Scan on test1  (cost=0.00..1887.00 rows=95076 width=21)Filter: (minor > 5000)
(2 rows)postgres=> explain select * from test1 where last < 8000  ;QUERY PLAN
------------------------------------------------------------Seq Scan on test1  (cost=0.00..1887.00 rows=8218 width=21)Filter: (last < 8000)
(2 rows)

带有第二列,第三列,或者它们两者独立作为条件,执行计划中都没有使用到索引。

总结


  • 在多列上创建索引时,必须把使用最频繁的列放在索引列的最前面;

  • 通过案例分析,可以看到只有在查询条件中带有第一列时,查询计划中才会用到索引,即使将条件中各列的顺序打乱,优化器也会按索引中的列的顺序进行查找路径。

  • 在使用多列索引时,避免出现案例中索引失效的场景。

结尾


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

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

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

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

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

相关文章

【微积分】CH16 integrals and vector fields听课笔记

【托马斯微积分学习日记】13.1-线积分_哔哩哔哩_bilibili 概述 16.1line integrals of scalar functions [中英双语]可视化多元微积分 - 线积分介绍_哔哩哔哩_bilibili 16.2vector fields and line integrals&#xff1a; work circulation and flux 向量场差不多也是描述某种…

gpt-4o继续迭代考场安排程序 一键生成考场清单

接上两篇gpt-4o考场安排-CSDN博客&#xff0c;考场分层次安排&#xff0c;最终exe版-CSDN博客 当然你也可以只看这一篇。 今天又添加了以下功能&#xff0c;程序见后。 1、自动分页&#xff0c;每个考场打印一页 2、添加了打印试场单页眉 3、添加了页脚 第X页&#xff0c;…

Leetcode刷题笔记1:数组基础1

导语 leetcode刷题笔记记录&#xff0c;本篇博客记录数组基础1部分的题目&#xff0c;主要题目包括&#xff1a; Leetcode 704 二分查找Leetcode 27 移除元素 知识点 二分查找 原理 二分查找的适用对象为有序数组且数组中无重复元素&#xff0c;其主要原理是每次都从有序…

2024年5月软考架构题目回忆分享

十年架构两茫茫 &#xff0c;Redis , UML 夜来幽梦忽还乡 &#xff0c; 大数据&#xff0c; Lambda 选择题 1.需求分析和架构设计面临这两个不同对象&#xff0c;一个是问题空间&#xff0c;一个是解空间 这是英文题&#xff0c;总共五个题目&#xff0c;只记得这么多 2. …

AI视频教程下载:全面掌握ChatGPT和LangChain开发AI应用(附源代码)

这是一门深入的课程&#xff0c;涉及ChatGPT、LangChain和Python。打造专注于现实世界AI集成的AI应用&#xff0c;课件附有每一节涉及到的源代码。 **你将学到什么&#xff1a;** - 将ChatGPT集成到LangChain的生产风格应用中 - 使用LangChain组件构建复杂的文本生成管道 - …

order by 优化

1. 排序方式 MySQL支持两种方式的排序&#xff0c;FileSort和Index&#xff1a; Index的效率高&#xff0c;它指MySQL根据索引本身完成排序。FileSort方式效率较低&#xff0c;是指MySQL自己扫描数据之后进行排序&#xff0c;没有使用到index 因此&#xff0c;我们要让order…

推荐五个线上兼职,在家也能轻松日入百元,适合上班族和全职宝妈

在这个瞬息万变的时代&#xff0c;你是否也曾考虑过在繁忙的工作之外&#xff0c;寻找一份兼职副业来补贴家用&#xff0c;同时保持生活的多样性&#xff1f;别急&#xff0c;现在就让我为你揭秘五个可靠的日结线上兼职岗位&#xff0c;助你轻松迈向财务自由之路&#xff01; 一…

云WAF与传统WAF:网络安全的双重防线

在网络安全领域&#xff0c;Web应用防火墙&#xff08;WAF&#xff09;是守护企业网络安全的重要盾牌。随着云计算技术的迅猛发展&#xff0c;云WAF作为一种新型的安全服务模式&#xff0c;正逐渐成为企业网络安全防护的新宠。本文将深入探讨云WAF与传统WAF的区别&#xff0c;分…

[‘column‘]和[:,‘column‘]的区别

之前&#xff0c;关于numpy和pandas的操作一直不熟悉&#xff0c;对于获取数据中的行&#xff0c;列一直混淆。 df[column] df[column]是 Pandas DataFrame 切片的常用语法&#xff0c;用于选择名为 column 的单个列。它返回一个 Pandas Series 对象。 df.loc[:,column] df[:,…

PSQL一些查询命令

只看10条数据 select * from dongchazhedata2 limit 10;以某一字段排序 select * from dongchazhedata2 order by date;查询大于某一日期的数据&#xff1b; select * from dongchazhedata where date > 2024-05-19;启动数据库命令 sudo service postgresql start;查看…

使用 Flask 和 Celery 构建异步任务处理应用

文章目录 什么是 Flask&#xff1f;什么是 Celery&#xff1f;如何在 Flask 中使用 Celery&#xff1f;步骤 1&#xff1a;安装 Flask 和 Celery步骤 2&#xff1a;创建 Flask 应用程序步骤 3&#xff1a;运行 Celery Worker步骤 4&#xff1a;启动 Flask 应用程序 结论 在构建…

高校网站群及融媒体中心建设方案

一、项目背景 随着信息技术的飞速发展&#xff0c;互联网已成为高校展示形象、传播信息、服务师生、沟通社会的重要渠道。然而&#xff0c;目前许多高校在网站建设和媒体传播方面存在以下问题&#xff1a; 网站分散、缺乏统一规划&#xff1a;各高校内部往往存在多个部门或学院…

家政项目day3 区域服务模块开发

目录 1 复习下业务流程2 接口设计2.1 查询区域服务2.1.1 接口梳理2.1.2 接口设计2.1.3 接口定义 1 复习下业务流程 区域服务管理是为运营地区设置要运营的服务项&#xff0c;不同地区所运营的服务项可能不同&#xff0c;比如&#xff1a;本平台在北京运营了老人陪护服务&#…

先进制造aps专题七 基于ai大模型的生产调度aps系统

"如果我们能够深度定制并开发出适合这些行业的大模型应用&#xff0c;将会带来巨大的变革。比如在医疗行业&#xff0c;大模型在医学图像分析、疾病预测和智能诊断方面有着广阔的应用前景。通过利用大模型技术&#xff0c;医生可以获得更准确的诊断辅助工具&#xff0c;从…

查数据库表以及视图sql

目录 oracle 数据表 视图 mysql 数据表 视图 hive 表 视图 pg 表 视图 oracle 数据表 SELECT a.owner AS owner,a.TABLE_NAME AS bywm,a.comments AS bzwm FROM all_tab_comments a where a.OWNER NOT IN (SYS, SYSTEM, CTXSYS, XDB, EXFSYS, MDSYS, OL…

零拷贝(Zero-Copy)

1.背景 现在有这样一个场景&#xff0c;我们需要在本地选择一个文件后&#xff0c;然后上传到网络上。 我们再看看文件的内容数据的具体搬运过程&#xff1a; 你会发现&#xff0c;在整个文件搬运的过程中&#xff0c;发生了多次的数据拷贝和上下文转换。 4次数据拷贝&#…

每日一题(5)——StringBuffer操作

编写程序&#xff0c;对StringBuffer对象进行追加&#xff0c;插入和修改缓冲区长度等操作&#xff1b; class StringDemo{public static void main(String[] args){boolean btrue;int i321;long l123456;String s1new String("Hello,world!");StringBuffer s2new S…

Rust一维Vec垂直方向拼接、水平方向拼接,多个二维Vec垂直方向拼接

1.在Rust中&#xff0c;拼接二维Vec通常意味着将多个一维Vec组合成一个二维Vec。假设你想要将多个Vec<T>拼接成一个Vec<Vec<T>>&#xff0c;你可以使用迭代器方法来实现。 下面是一个示例&#xff0c;演示如何将多个一维Vec拼接成一个二维Vec&#xff1a; …

深入探索:移动云服务器的强大之处

文章目录 一 什么是移动云二 移动云服务器的使用三 移动云服务器的优点四 在移动云上部署node.js项目五 移动云服务器的应用场景六 移动云服务器的使用体验总结 一 什么是移动云 移动云是指用户可以通过移动设备访问云端的数据和应用&#xff0c;无需在本地设备上进行存储和处…