用传统的LIMIT m, n
做分页查询需要这么几步:
用SELECT COUNT(*) FROM table WHERE condition ORDER BY ...
查到总数并算出有多少页;
用SELECT columns FROM table WHERE condition ORDER BY ... LIMIT 0, 100
显示第一页(假设每页有100行),如果用SQL_CALC_FOUND_ROWS
这个参数的话,可以跟前一条合并成一条SQL;
点“下一页”时,用SELECT columns FROM table WHERE condition ORDER BY ... LIMIT 100, 100
查;
...
这样做往往花费很大,因为WHERE condition
有可能是全表扫描。如果MySQL没开缓存的话,每翻一页可能非常慢。
因此我就用一种新的办法:
用SELECT id FROM table WHERE condition ORDER BY ...
得到所有相符的ID,如果数据量太大(比如表中有1,000,000行),我们就限制一下行数(比如限制最多查10,000,就用LIMIT 10000
),于是这些ID就通过动态页面或Ajax(以JS代码或JSON的形式)被传到了前端;
前端JS选取前100个ID作为第一页,发送一个带这100个ID的查询请求,后端其实处理SELECT columns FROM table WHERE id IN (id_0, id_1, ..., id_99)
这么一个查询;
点“下一页”时,查询是SELECT columns FROM table WHERE id IN (id_100, id_101, ..., id_199)
;
...
这种方法只需要做一次条件查询(慢),列表数据其实都是主键查询(快)。
我在一个业余项目中用了这个办法,详见:(http://) www.chess-wizard.com/base/ (第一页数据被写在JSP页面里,有利于SEO).
我要求团队成员都用这种方式来处理分页,他们却并不认同 :-(
难道LIMIT m, n
是分页查询的标准做法或唯一途径吗?
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…