簡體   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