(1)待查询表中的数据超过4000万条; (2)已经对sql的进行过优化,对表结构等进行优化,并且已经对sql中的查询条件都添加了索引; (3)前端分页需要的数据格式如下:
{ "total": 0, "data": [] }(1)方法一:
不告诉前端总的数据量,不传total值。让用户一直点击“下一页”,当点击后返回数据为空,即表示已经到了最后一页。此时按钮变为不可用状态。这种做法的好处是,只执行一个分页的sql,效率比较高。 如下: { "data": [] }(2)方法2:
但是为了不影响(或者降低)用户体验,增加一个参数,“isStill,表示是否还有下一页”。该参数为true表示有,false表示无。此时,后端需要执行两个分页的sql,每次查询都多执行后一次的分页。这种效率比count()的效率要高很多。 { isStill:true, "data": [] }(3)方法3:
把查询总条数和查询源数据分为两个接口。每次查询时,只是分页的第一页需要同时查两个接口。并且当查询条件改变时,需要同时查两个接口。由前端判断查询条件是否改变了。注意,在查询总条数时,务必对sql进行简化,越简单越好。 (该方案,其实还有一种实现,就是由后端对总条数进行缓存(可以放内存/redis中),由后端判断查询条件是否改变。但是我建议使用前端判断的方法)方法一: 缺点是,用户不知道下一页是否还有数据,只有当点击了下一页按钮后才会知道; 优点是,效率高;
方法二: 缺点是,多执行了一个分页的sql,效率较低; 优点是,用户体验好一些;
方法三: 个人推荐!
在执行count()查总条数的sql时,使用最简单的sql进行(比如,去掉排序,去掉多余的表联合,使用count(1)代替count(*)等); 但是,如果连第一次count()都慢的查不出来时,那就没办法了,要不做分表分库,要不使用方法二。
慢查询一是,会严重降低数据库性能,如果有多个应用程序都需要操作数据库的话,会导致所有应用都无法使用(我在生产环境就遇到了这个问题,非常严重的问题,生产环境中整个系统无法使用,原因就是mysql卡死);二是,数据查询非常慢,用户等待时间过长,用户体验非常差,而且还可能造成前端请求超时。