繁体   English   中英

分页偏移问题 - MySQL

[英]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开头的索引。 但是, LIMITOFFSET可能会合谋要求读取表格的 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM