zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

POSTGRESQL index-only-scan 到底开不开 与 我 羊 了

2023-02-18 16:28:14 时间

最近的任何人之间的问候语,与时俱进,见面一般第一句是,你阳了吗?然后就很容易打开话题了,至于阳不阳,这个问题,其实我是这样看的,你先在没阳,不证明你明天不阳,你阳过了,也要继续包含自己,持续增加自己的免疫力,锻炼身体,从现在开始爱护自己。有的时候问题的两方面看,从疾病中学到点什么,也不枉这3年,大家所付出的。努力的改变,欣然的接受,坦然的面对,然后在努力的改变,让自己持续的处于一个自己满意的状态。写这篇的时候,我已经感觉不大好了,可能已经阳了,这篇也许是最近能更新的最后一篇了,祝我好运吧。

最近问问题的同学挺多的,也有问有没有群的,实在是忙没有建群,所以问的人多了,想想还是建一个群,但本人写文章不懒,其他的比较懒,因为问POLARDB 的问题的多,所以建立了一个 POLARDB 和 PG ,MYSQL ,MOGNODB ,REDIS 以及文章问题的讨论群。希望能帮助自己也帮助大家共同提高,要进群的,可以添加微信 liuaustin3 ,来申请加群.

说完这一堆,有的没的,咱们的说到今天的主题了,POSTGRESQL 的INDEX ONLY SCAN ,因为最近我们遇到一个比较“诡异” 的现象,POSTGRESQL 的一个从库的执行的语句,一会快,一会慢。从几百毫秒,到几十秒。跨度还挺大的,那么到底一个语句到底为什么这样,的说说。

关键的地方在于 index -only -scan 这个POSTGRESQL 的功能,在使用中会不会出现一些问题,index-only-scan 为什么会产生这些问题。

首先INDEX ONLY SCAN 产生于的思路是加快数据回馈的速度,也就是在扫描的情况下,数据的查询不会在回表。那么首先使用INDEX ONLY SCAN 的主要因素在于查询中的有适合的索引。

我们可以看到,在POSTGRESQL 中开启了index only scan ,从执行计划和执行的时间上看。

下面我们将这个部分index-only-scan 关闭,查看情况。

第二种方式可以看到,将index only scan 关闭后,整体的查询的方式和选择的索引都变化了,虽然速度还是类似的,这里很明确的回表了。

首先这个索引本身在有些数据库中叫覆盖索引,也就是查询的return 的数据覆盖了整体的数据,也就是说,PG 如果要使用INDEX ONLY 必须有两个条件。

1 INDEX ONLY SCAN 打开

2 有合适的索引

在这样的情况下,很适合走 index only scan 索引,不通过回表的方式,直接通过INDEX 来将数据返回。

那么这里产生两个问题

1 我是用索引覆盖 还是用单索引,还是用include方式来进行数据的索引建立

2 一般的情况 index-scan-only 开不开

那么我们下面做一个实验,我们建立一个表,5百万的表

我们分别用以下的几种索引来尝试查询的效率

1 单列索引 age 和 salary ,分别建立两个索引,然后查询的结果包含name

2 复合索引,其中查询的索引包含这三列

3 include 索引 ,复合的age + salary 加include name

可以看到第一种方案中如果是分别建立两个索引的情况下,最终的结果是使用了单个索引来进行查询,并且回表了。

查询的效率比之前的查询效率要高1.2倍左右。

那么问题来了,在什么情况下会出问题,这里测试环节在PG 14 版本中,这里只要使用ORDER BY ,那么INDEX-ONLY-SCAN ,这边立刻会出现问题,

查询速度比较值钱慢了4倍之多,就是因为多了一个排序的部分,并且这部分不再索引内造成的。

具体分析一下首先如果没有排序的情况下,走的是我们标准的index-only-scan, 但是加了排序后,我们整个的过程就复杂了,直接走的是bitmap index scan ,然后多了一个 external merge 的部分对排序进行处理。

然后我们在将问题深入,将index only scan 关闭后看结果。在关闭后,我们发现整体的执行计划相对于原来的执行计划时间较少了100毫秒,并且不再有external merge 的部分。这里仅仅是关闭index only scan的情况。

那么这里我们将index only scan 打开,然后将id 作为索引的一部分,我们看看结果如何。

可以看到,执行的结果虽然已经走了我们建立了联合索引,但是这里还是有 extrnal merge 的部分。

写到这里,我浑身骨头疼,下面就简短说说 external merge, 出现这个情况是告知你的 process 的 work_mem 设置的少了,所以导致外部通过磁盘的方式来进行排序的处理。

在坚持一下,我调整我的虚拟机中的work_mem,看看情况是不是好转了,果然调整后,整体的操作的计划变化了,已经走了 quicksort : memory ,但是操作的速度并没有加快。但是情况并没有如愿,甚至还慢了。

而我再次关闭 index-only-scan ,查询的速度又提高了。我的结论是,如果你的PG 中存在大量的ORDER BY 并且不用ORDER BY 就很快,用了就很慢,那么你先试试关掉 INDEX-ONLY-SCAN 试试,速度有没有提升。

实际上,还有很多东西需要研究,留到下一期,现在脖子,腰子,角统统的痛,嗓子和含了一个开水做的球一样。

本周估计是不能更新了,下周咱们见,阳了个阳, I AM BE OK !!