我正在使用超过2百万条记录的"用户"表.查询是:
SELECT * FROM users WHERE 1 ORDER BY firstname LIMIT $start,30
Run Code Online (Sandbox Code Playgroud)
"firstname"列已编入索引.获取第一页非常快,而获取最后一页非常慢.
我使用了EXPLAIN,结果如下:
对于
EXPLAIN SELECT * FROM `users` WHERE 1 ORDER BY `firstname` LIMIT 10000 , 30
Run Code Online (Sandbox Code Playgroud)
我越来越:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE users index NULL firstname 194 NULL 10030
Run Code Online (Sandbox Code Playgroud)
但对于
EXPLAIN SELECT * FROM `users` WHERE 1 ORDER BY `firstname` LIMIT 100000 , 30
Run Code Online (Sandbox Code Playgroud)
我越来越
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE users ALL NULL NULL NULL NULL 2292912 Using filesort
Run Code Online (Sandbox Code Playgroud)
有什么问题?
您不应该使用 limit 来对数据集进行分页。
通过使用范围查询,您将获得更好的结果。
SELECT * FROM users
WHERE firstname >= last_used_name
ORDER BY firstname
LIMIT 30
Run Code Online (Sandbox Code Playgroud)
您已经见过的一个在哪里last_used_name(我假设您进行某种批处理)。如果对具有唯一索引的列进行范围查询,您将获得更准确的结果。这样您就不会两次获得相同的记录。
当你这样做时
LIMIT 100000 , 30
Run Code Online (Sandbox Code Playgroud)
MySQL 本质上与
LIMIT 100030
Run Code Online (Sandbox Code Playgroud)
只是它不会返回前 10 万个。但它会对它们进行排序和读取。