[英]Pagination Offset Issues - MySQL
我有一个包含 100 万条记录的订单网格。 该页面具有分页、排序和搜索选项。 因此,如果排序顺序是由带有搜索键的客户名称设置的,并且页码为 1,则它工作正常。
SELECT * FROM orders WHERE customer_name like '%Henry%' ORDER BY
customer_name desc limit 10 offset 0
当用户单击最后一页时,它会成为一个问题。
SELECT * FROM orders WHERE customer_name like '%Henry%' ORDER BY
customer_name desc limit 10 offset 100000
上面的查询需要永远加载。 索引设置为订单id、客户名称、订单日期列。
如果我没有非主键排序选项,我可以使用此解决方案https://explainextended.com/2009/10/23/mysql-order-by-limit-performance-late-row-lookups/ ,但是在我的情况下,排序是用户选择的。 它将从订单 ID、客户名称、订单日期等更改。
任何帮助,将不胜感激。 谢谢。
问题1:
LIKE "%..."
-- 前导通配符需要对数据进行全面扫描,或者至少直到它找到 100000+10 行。 甚至
... WHERE ... LIKE '%qzx%' ... LIMIT 10
是有问题的,因为可能没有 10 个这样的名字。 所以,全面扫描你的百万个名字。
... WHERE name LIKE 'James%' ...
将至少从表的中间开始——如果有一个以name
开头的索引。 但是, LIMIT
和OFFSET
可能会合谋要求读取表格的 rest。
问题 2:(在您编辑问题之前!)
如果你省略WHERE
,你真的希望用户翻阅一百万个名字来寻找东西吗?
这是一个用户界面问题。
如果您有一百万行,并且 output 是按 Customer_name 排序的,那么很容易看到 Aarons 和 Zywickis,但看不到其他任何人。 你会怎么找到我(詹姆斯)? 要么你有 100K 链接,而我在中间的某个地方,要么可怜的用户将不得不按 [Next] 'forever'。
我的观点是,数据库不是引入效率的地方。
在其他一些情况下,go 到[Next](或[Prev])页面是有意义的。 在这些情况下,“记住你离开的地方”,然后用它来有效地进入桌子。 OFFSET
效率不高。 更多关于分页
我为此使用了一个特殊的概念。 首先,我有一个名为pager
的表。 它包含一个主要的pager_id,以及一些用于标识用户的值(user_id,session_id),这样pager 数据就不会被窃取。
然后我有第二个名为pager_filter
的表。 我由 3 个 id 组成:
pager_id int unsigned not NULL # id of table pager
order_id int unsigned not NULL # store the order here
reference_id int unsigned not NULL # reference into the data table
primary key(pager_id,order_id);
作为第一个操作,我 select 匹配过滤器规则的所有记录,并将它们插入到pager_filter
DELETE FROM pager_filter WHERE pager_id = $PAGER_ID;
INSERT INTO pager_filter (pager_id,order_id,reference_id)
SELECT $PAGER_ID pager_id, ROW_NUMBER() order_id, data_id reference_id
FROM data_table
WHERE $CONDITIONS
ORDER BY $ORDERING
填充过滤表后,您可以使用内部联接进行分页:
SELECT d.*
FROM pager_filter f
INNER JOIN data_table d ON d.data_id = f.reference id
WHERE f.pager_id = $PAGER_ID && f.order_id between 100000 and 100099
ORDER BY f.order_id
或者
SELECT d.*
FROM pager_filter f
INNER JOIN data_table d ON d.data_id = f.reference id
WHERE f.pager_id = $PAGER_ID
ORDER BY f.order_id
LIMIT 100 OFFSET 100000
提示:以上所有代码都不是经过测试的伪代码
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.