数据库 频道

用好索引在PG优化中很重要

今天继续写一篇PG方面的技术文章,MySQL/PG等数据库因为没有了共享池这种机构,因此在运维上十分方便。虽然说没有了共享池,执行计划只能会话内共享,因此在SQL编译上开销大了不少。不过也是因为这种特性,让数据库变得更为简单,对于运维来说是一件大好事。随着现代硬件在CPU处理能力上的提升,每秒钟产生大几千个SQL PARSE问题也不算很大。在PG数据库优化方面,也要比Oracle简单的多,实际上我觉得,很多PG数据库的优化工作都可以从索引入手,把PG数据库的索引用好了,那就事半功倍了。

Oracle的索引种类有限,大家翻来覆去也就那么几种常用的,而PG数据库则不同了,常用的索引种类有十多种,如何在某些场景中通过索引种类的改变来优化应用就十分重要了,关于PG索引种类的问题,我以前写过几篇文章,大家有兴趣可以去阅读。我等会儿在公众号里设置一个POSTGRESQL的搜索词条,帮大家把相关资料汇总在一起。

今天我要给大家分享的是部分索引和覆盖索引,实际上我们的很多应用系统中都可能会遇到类似的应用场景,而以习惯而言,我们会中规中矩的使用与Oracle类似的方法来创建索引,实际上在PG数据库里我们完全可以采用一种新的思路来建索引。

比如我要做select avg(score) from join2 where id<100 or="" id="">10000 and id<10009)。这个WHERE条件是我为了做实验而设定的。

没关系,我们在ID上建个索引再来看看效果。

可以看出,使用索引后,从31毫秒缩短为1.82毫秒了。我们还可以如何优化这条SQL呢?

可以看出,如果我们在ID上创建了一个部分索引,执行计划变得更好了,两个BITMAP INDEX SCAN变成一个了。可能有朋友觉得执行时间没有提升反而下降了,实际上对于数据量较小的场景,1.82毫秒和2.166毫秒是看不出好坏的。PG数据库的SQL执行时间也不是很稳定的,有些偏差很正常。比如上面1.82毫秒的哪个场景,我们再做一次就变成2.168毫秒了。

我们还可以继续优化吗?可能大多数朋友觉得到此差不多了,实际上还可以继续优化,在Oracle数据库上还是可以继续优化的。那就是通过添加冗余字段,让SQL不需要回表。

如果我建一个(id,score)的索引,那么执行计划变成index Only Scan了,执行成本进一步降低。

不过如果你使用的是PG数据库,那么并不能满足于刚才的这种索引创建策略,PG数据库支持gen够强大的索引类型-覆盖索引。如果创建(id,score)的索引,那么索引键包含两个字段,如果索引比较大,那么和覆盖索引中间的效率还是会有些差异的。因为覆盖索引中的附加字段不是作为索引字段的,而是作为一个附加存储数据存放的,覆盖字段的存在不会影响索引树的大小。我们来看看覆盖索引的效果:

今天我们通过一个简单的场景学习了部分索引,覆盖索引以及二者的组合覆盖+部分索引。也可以看出PG数据库索引的强大了。强大的功能就需要用好它,因此让开发人员了解这些就十分关键了。

0
相关文章