最近碰到了一个关于PostgreSQL查询慢的问题,表中数据共有40W,在做分页查询的时候,COUNT竟然花了20s,而且这个还是不稳定的,有时甚至能飙到40s,这个时间真的是让人不能接受。

来张图大家感受一下,抓包看到请求的TTFB竟然有26s多,真让人害怕

PostgreSQL分页count超级无敌巨慢

在没具体细看的时候,我第一反应是数据太多,limit查询太慢导致拖慢了整个请求,后来在Navicat中查询了一下,发现limit响应还是很快的,甚至是毫秒级别的响应,问题分析到了这里,都还没想到是count出了问题。

多次测试之后,发现每隔一段时间查询就会慢一次,而连续操作则很流畅,分析可能是由于在mybatis中加了二级缓存,所以在第一次以后的查询时,速度又很快。

期间朋友想到是否可能是count太慢,我当时心里觉着不可能,但还是将sql打印出来看了一下,结果分分钟打了我的脸,还真的是count耗时太久

PostgreSQL分页count超级无敌巨慢

上图中我用红色框起来的sql,第一次查询耗时30s,以为是where条件没有加索引导致了全表扫描,检查之后发现是有索引的

PostgreSQL分页count超级无敌巨慢

没办法,只能找度娘,竟然发现不是我一个人这样,甚至有比我更惨的,3W数据查询上20s的都出现过,实在是不明白为什么这么好的一个数据库,为什么在这块儿设计上有这么大的缺陷?

我也一度怀疑过是否服务器的磁盘和CPU不行了

我也一度怀疑过是否pgsql的版本过低是否高版本已经优化了这个问题

继续查阅资料,后来找到了一种方案,使用pg_class表,速度是快了很多,毫秒级别响应,但是却带不上where条件,如下:

PostgreSQL分页count超级无敌巨慢

继续百度,发现有大佬提出一个方案,创建一张计数表,加上触发器,监测insert、delete操作,实时同步数量,不失为一个好方法,但是我又不想在这么一个问题上单独建一张表处理,最后虽然不想使用此方法,但却受到了启发,不想建表,那就用缓存呀~

临时解决方案:

1、利用pg_class查询,但是却无法带上where条件,全表扫描时可以考虑;

2、建立计数表,insert和delete之后,实时更新数量;

3、定时查询符合条件的数量,存入缓存;

此问题,可以说是依旧没有解决,我选择的第三种方案,只不过是避开了实时查询慢的问题,在定时器中查询的时候,依旧很慢,不过这个慢只有代码知道,对于用户是无感的!

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐