2017-02-01 53 views
1

我有一張非常大的表,我想從中刪除舊行。表的例子:如何從大型MySQL表中高效地刪除過期的行

| customer_id | first_purchase_date | last_purchase_date | 
|<primary key>|      | <index>   | 

**我使用這個示例表爲參數的緣故。有問題的表不是客戶表。真正的桌子在過去的2個月裏已經增長到28GB,用於計算僅需要2周曆史數據的東西。

我想要做的就是從該表還沒有在過去的一年裏購買任何東西刪除客戶。即delete from table where last_purchase_date < now() - interval 1 year;

的simpy刪除這樣會在數據庫上過於昂貴。我知道一個分區可以用來截斷舊的行,但我不知道如何有效地實現它。

此外,如果客戶要購買的東西,然後該行可能通過更新last_purchase_date移動到不同的分區。這不會太貴嗎?

預先感謝您的任何方向!

+0

您確定要刪除您的客戶嗎? –

+1

如果性能是您的問題,Partinion on date可以獲得更好的結果,但這是您的問題嗎?什麼是「一張非常大的桌子」?給一些數字。刪除客戶不是一個好主意,將他們轉移到「存檔」表格會更好。你打算如何刪除它們?將是一個每年的過程(到2017年底,刪除全部2016年)或每日過程(每天結束時,刪除那些<[date - 1year])。總之,你真的需要添加更多的信息 –

+0

有問題的表不是真正的客戶羣 – AYR

回答

2

你是正確的思想,partitioning是前進的方向,這是因爲:

數據失去其實用性往往可以很容易地從一個 分區表被丟棄分區(或分區)只含 刪除該數據。相反,添加新數據的過程可以在一些 情況下通過添加專門存儲該數據的一個或多個新分區來極大地促進。

如果這不適合你,它仍然可能

此外,MySQL的5.7支持 查詢明確的分區選擇。例如,SELECT * FROM噸PARTITION(P0,P1)其中C 只選擇在分區P0和P1匹配WHERE 條件的那些行。在這種情況下,MySQL不檢查表t的任何其他分區 ;當你已經知道你想要檢查的分區或分區時,這可以大大加快查詢速度。分區選擇 也支持數據修改語句DELETE,INSERT, REPLACE,UPDATE和LOAD DATA,LOAD XML。

既然你想刪除基於日期而不是主鍵的東西,你需要的是一個RANGE分區方案。

首先找到的最早日期和創建基於

ALTER TABLE sales 
    PARTITION BY RANGE(TO_DAYS(last_purchase_date)) (
    PARTITION p0 VALUES LESS THAN (TO_DAYS('2018-12-31')), 
    PARTITION p1 VALUES LESS THAN (TO_DAYS('2017-12-31')), 
    PARTITION p2 VALUES LESS THAN (TO_DAYS('2016-12-31')), 
    PARTITION p3 VALUES LESS THAN (TO_DAYS('2015-12-31')), 
    .. 
    PARTITION p10 VALUES LESS THAN MAXVALUE)); 

分區選擇分區的適當數量而不用擔心太多,因爲你可以隨時更改分區後。當你分區時,你甚至可能會發現刪除步驟並不是真的需要。

+0

使用'PARTITIONing'是促進刪除舊行的好方法。 [_Here_](https://mariadb.com/kb/en/mariadb/partition-maintenance/)就是我的博客。 –

+0

@ e4c5謝謝您的詳細解答。問題是如果使用分區不會顯着影響日期列上的更新,因爲它必須將行移動到不同的分區。 – AYR

+0

哎呀,抱歉,如果日期不斷變化,這個方案將無法工作。它必須是靜態的。你可以發佈你的全表,這樣我們可以確定一個合適的列 – e4c5