去年年中做了一个用户权益的控制功能,其中查询用户权益历史记录接口测试同学压测发现100(线程)*100(循环)的情况出现,部分请求超过10S相应&很大一批数据出现超过1S的情况。用户量1000W+,表数据2000W+。多次测试性能差距较大,多次测试发现的特征是:分页设定为(2~5)页的情况出现并发性能特别差,分页设置为10的情况并发性能立马提升。
1、针对设定分页设定为5的情况
下面语句索引包含uid、update_date 两个单独索引(update_date主要是考虑后续的数据统计和分析使用需要),PG查询优化器根据updated_date 进行索引
2、分页设置为10 的情况
查询计划是按照uid进行查询的,根据uid索引之后的数据量就比较小了,性能会立马提升
根据explain获取执行计划之后,查看了测试环境数据的分布情况,发现数据分布集中在update_date某个固定的时间段内。所以分页选择limit2并且根据update_time desc的情况,PG的查询优化器就会自动选择update_date作为索引,由于数据集中分布在update_date某个时间段,导致索引之后的数据量仍然非常大,需要通过uid进行filter过滤,导致性能非常差。强制删除update_date字段的索引之后,查询强制走UID索引,性能明显提升。
PG没有类似Mysql 强制索引查询的指令(MySQL使用force index(update_date)),故涉及到PG查询分页的情况,当存在排序和过滤两个字段均有索引的情况,最好先评估数据的分布情况,看看执行计划,评估脚本性能。