Mysql

小批量無重複處理數據的最快查詢

  • March 8, 2022

我有在後端使用 MySQL 的 java 應用程序。我有下表:

A = int, B = varchar, C = timestamp

A | B   | C
1 | 100 | 2022-03-01 12:00:00
2 | 200 | 2022-03-01 12:00:01
3 | 100 | 2022-03-01 12:00:01
4 | 200 | 2022-03-01 12:00:02
5 | 600 | 2022-03-01 12:00:03
1 | 100 | 2022-03-01 12:00:06
5 | 700 | 2022-03-01 12:00:07
2 | 200 | 2022-03-01 12:00:08
9 | 100 | 2022-03-01 12:00:08

每 X 秒,查詢應該執行一次,它應該處理 5 條記錄 where column C > LAST_PROCESSED_TIMESTAMPLAST_PROCESSED_TIMESTAMP每次執行後都會更新。

我需要的是 - 我想選擇這 5 行,但如果 A 和 B 列將在將來發生的某些提取中重複,則不包括這些行。

範例:對於上表:

第一次執行 - 選擇 5

1 | 100 | 2022-03-01 12:00:00 <–未選擇,因為它處於第 2 輪

2 | 200 | 2022-03-01 12:00:01 <–未選擇,因為它處於第 2 輪

3 | 100 | 2022-03-01 12:00:01
4 | 200 | 2022-03-01 12:00:02
5 | 600 | 2022-03-01 12:00:03

秒跑 - 選擇 5

1 | 100 | 2022-03-01 12:00:06
5 | 700 | 2022-03-01 12:00:07
2 | 200 | 2022-03-01 12:00:08
9 | 100 | 2022-03-01 12:00:08

在第一次執行中,我們不選擇1|100and 2|200,因為它將在第二次執行中被選中。

我已經有一些解決方案,但是選擇花費了太多時間。數據庫也很大——所以我試圖找到最快的方法來執行它。我應該優化哪些指標?哪種查詢?

我嘗試了什麼:

SELECT  *
   FROM ( SELECT  A,B
           FROM  TABLE
           WHERE  C &gt;= '2022-03-01 12:00:00'
           LIMIT  5
        ) a
   LEFT JOIN (
       SELECT  A,B
           FROM  TABLE
           WHERE  C &gt;= '2022-03-01 12:00:00'
           LIMIT  5, 18446744073709551615
             ) b  ON (     a.A=b.A
                      AND  a.B=b.B
                     )
   WHERE  b.A IS NULL;

還有(這個可能不行,因為即使不在前 5 個中,它也會選擇 C 的 MAX,所以對於我的範例,它將包括2 | 200 | 2022-03-01 12:00:08第一次執行的內部 - 這不是我需要的):

SELECT  A, B, MAX(C)
   FROM  TABLE
   WHERE  C &gt;= '2022-03-01 12:00:00'
   GROUP BY  A, B ASC
   LIMIT  5;

我已經有一些解決方案,但是選擇花費了太多時間。

通過創建索引(C,A,B)。然後尋找執行計劃——如果索引沒有被使用,那麼嘗試強制使用它。

我試過的

過於復雜。採用

SELECT * 
FROM table 
WHERE C &gt;= '2022-03-01 12:00:00' 
ORDER BY C, A, B LIMIT 5;

每隔 X 秒,應該執行一次查詢,它應該處理 5 條記錄,其中列 C > LAST_PROCESSED_TIMESTAMP。每次執行後都會更新此 LAST_PROCESSED_TIMESTAMP。

不足以進行確定性處理。

假設C中有6行時間戳相同,A和B不同,處理的行不超過5行,並保存它們的時間戳。下一次執行這個時間戳被應用……但現在我看不到確定已經處理了 6 行的哪些行以及現在要處理的其他行的方法。

添加一個將儲存標記“此行已處理”的列。在為目前處理選擇 5 行的查詢中使用此列。

這些將有助於您的第一次嘗試:

INDEX(C,A,B)
INDEX(A,B,C)

為了弄清楚如何簡化或改進查詢,從折騰開始b。它只會增加問題的複雜性。a只用和思考問題c

更多的

  1. 從“輸入隊列”中拉出 5 行
  2. 辨識“dups”(可能使用LEFT JOINand IS NOT NULL,或使用NOT EXISTS ( SELECT 1 ... )
  3. 儲存非重複數據(可能在步驟 2INSERT ...的前面)SELECT
  4. 將 dups 推回輸入隊列(DELETE從隊列中?)`

A “dup” 是 A 和 B 都匹配的地方。

引用自:https://dba.stackexchange.com/questions/308381