Postgresql 建索引性能优化

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Postgresql 建索引性能优化相关的知识,希望对你有一定的参考价值。

参考技术A 客户新上线了一套监控系统,可以监控到所有的执行慢的SQL,监控到有个批量任务导入大量数据后,进行索引创建。耗时需要几分钟,虽然不影响业务,但是需要整改。

这种问题的处理思路,都是大拆小,搞并发。

在测试环境,创建一个大表进行测试,创建大量的假数据。

创建表

随机字符串生成函数

生成大量的数据

经测试发现这种方法创建数据太慢了,改成使用COPY的方式创建数据。
排查发现random_string效率太低,生成一条数据接近1ms

重新创建表

写程序创建8600万条数据放在test.csv中
导入大量数据

测试基准数据

\timing 开启计时

耗时532824.434 ms

耗时385838.893 ms,提升 38%的性能,非常不错,但是远远不够。
仍然会出发告警。

重新创建表

创建分区

并发创建INDEX,并记录每个分区索引创建的开始时间和结束时间;
耗时 = 最大结束时间 - 最小开始时间 = 137 s,速度提升接近4倍。

顺序创建INDEX,并记录每个分区索引创建的开始时间和结束时间;
耗时 = 每个索引的耗时相加 = 457358.14 ms,速度提升 16.5%

顺序创建INDEX,优化并发

耗时 = 每个索引的耗时相加 = 292027.642 ms, 速度提升接近两倍。

在开启了并发参数的情况下,如果再叠加并发分区INDEX创建,会不会有惊喜呢?
并发创建INDEX,并记录每个分区索引创建的开始时间和结束时间;
耗时 = 最大结束时间 - 最小开始时间 = 141 s,速度还不如默认并发参数下的表现。应该是资源发生争抢导致的,通过系统监控发现CPU已经打满了。

分区并发是目前能想到的最优化手段了。

还需要结合查询的情况进行分析,分区会带来一点点的性能下降是否影响也需要考虑一下。

分区时目前能避开监控报警的唯一手段了,另外还钻了监控报警的空子。
客户的监控是基于单条语句的,单个分区的最大创建时间为47s,控制在分钟以内了。

MYSQL 性能优化 -- index 使用方法公式


MYSQL

在数据查询中,大多数情况都需要使用索引来加速数据的查找,而索引本身是一种数据存储的结构,通过特殊的数据的存储结果来对应数据的访问的算法,本身索引的高效率 = 算法 + 数据存储的方法 , 缺一不可,所以不同的索引页需要不同的数据存储的组织方式,这里统称为索引的类型。


在不同的数据库中有不同的索引类型,这里POSTGRESQL 的索引类型是目前数据库中类型最多的,MYSQL的索引类型是常规的主要分为以下几种


1  主键

2  唯一索引

3  二级索引

4  覆盖索引


同时本期将说说索引的限制


1 主键

主键在mysql中与其他数据库不同,MYSQL的数据与主键是在一起的,也就是主键和数据本身是一个整体,当然数据本身在根节点和子叶子节点上提供的是主键和指针,最下面一层才是主键数据和行数据本身,在MYSQL中主键的效率要比其他的数据库效率要高,同时也就提出一个需求,就是MYSQL的主键尽量要小一些,这有利于在同样的访问效率下,可以减少I/O的访问情况下,进来访问更多的数据。但这样的设置并不是说,一定要使用自增的ID 的方式来使用MYSQL 主键,对于大型的分布式系统,浪费一些主键的存储空间是必然的,但有一点你的主键尽量是要有序的,无序的雪花算法对MYSQL的系统数据的插入是一种天然的伤害。


2  唯一索引

唯一索引,提到唯一索引的问题,大部分开发人员都会想到方式数据重复的一种方式,而唯一索引的使用中,也是讲求效率的,唯一索引应该是短小的是可以灵活的,而不是多个字段的混合的产物,经常见过一些唯一索引设计的三到四个字段组成一个唯一索引,我一看就知道这个开发的水平   一般。

为什么,唯一索引主要的功能是在数据插入的时候进行数据检测,而唯一索引作为与其他索引不同的地方,就是检测和数据的插入有一个原子性,否则检测完不冲突,而在插入的时候,同时又其他同样的数据插入,那么不就产生无可预测的数据冲突,所以唯一索引是一个会在数据插入的时候产生复杂锁的一种索引,而让这个锁能快速的检测,并且解锁,这才是一个好的设计。

所以通过将多个字段进行hash的方式,产生一个字段,而将这个字段进行唯一索引是一种解决多个字段进行唯一索引的方法,具体HASH算法可以按照不同的情况而定。所以唯一索引一般在一个数据表中最多只有一个,而不是多个,字段也最好只有一个,而不是多个。


3  二级索引,secondary index ,这是一个经常被使用的索引,而二级索引本身到底应该怎么使用,通常一个简单的查询中需要的索引很好被建立,而一个复杂的查询的索引建立是困难的,你查询条件中的N 个条件到底哪个才是应该被应该建立索引的,而不是一股脑的把这些索引都建立上,那样只能叫事倍功半, 我们需要的索引是事半功倍。那么这就涉及到数据的分布的问题了,这里有一个公式,

1   数据分散 + 查询条件为等于, 这是一等使用方式

2   数据集中 + 查询条件为范围, 这是二等使用方式

3   数据分散 + 查询条件为范围, 这是三等使用方式

4   数据集中 + 查询条件为等于, 这是四等使用方式

同时将多个字段的索引建立的方式限定在

1 2 3 4 建立的次序上,相信你的查询速度应该是最优选。


4  覆盖索引

覆盖索引本身在MYSQL中是否应该被使用是一个需要被评估的事情,这基于MYSQL 本身并未有include 索引的能力, sql server , postgresql都具有这样能力,这样的好处是方式在使用覆盖索引的时候,增加本身索引的单行的尺寸限制,同时降低这些字段参与索引的使用时的计算。基于MYSQL 没有这样的功能,所以在MYSQL中使用覆盖索引是一个小心的事情,如果不确认的情况下,可以不使用,这里也有一个公式

1   添加的字段既是索引字段也是返回的的字段

2   添加的字段部分索引字段但是全部返回的字段


除此以外覆盖索引在MYSQL中就不应该被使用,当然也有例外,如果你的索引量已经确认,但经常要反馈一个比较大的字段如VARCHAR(200) 等作为值反馈,那么可以添加这个字段在索引中,当然这也是一个双刃剑,你插入数据的时候,一定不会有一个好的感受。


最后说一说MYSQL的索引的限制,


1 每行最大的支持的索引的字节数是 3072  并且表必须是dynamic的方式

2 BLOB TEXT 这两种字段如果非要使用索引,那就使用 FULL TEXT 的索引方式,而不是普通索引

3  一个表最多是能有 64个二级索引(当然这应该也不算一个限制)

4  一个复合索引最多只能承受16个column的数量


当然最后一句是如果可以使用前缀索引那么还是使用前缀索引,更有利于你的索引使用。


下期我们继续说说MYSQL 的索引的总结 2  具体的索引类型 如 hash  index   前缀索引 ,隐藏索引 等等

MYSQL


以上是关于Postgresql 建索引性能优化的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL 性能优化创建正确的索引具有不确定性开源软件联盟PostgreSQL分会

浅谈Solr和ElasticSearch建索引性能优化策略

数据库性能优化(database tuning)性能优化绝不仅仅只是索引

确定应该在 DB2 中创建哪些索引以优化特定查询的性能

SQL Server 查询性能优化——创建索引原则

请教ABAP性能优化-关于MSEG