簡體   English   中英

mysql - 從InnoDB刪除行非常慢

[英]mysql - Deleting Rows from InnoDB is very slow

我有一個mysql數據庫約。 1 TB的數據。 表fuelinjection_stroke有apprx。 1.000.000.000行。 DBID是每個插入時自動遞增1的主鍵。

我試圖使用一個非常簡單的語句刪除前1.000.000行:

Delete from fuelinjection_stroke where DBID < 1000000;

在我的專用8核Xeon服務器(32 GB內存,SAS存儲)上,此查詢需要很長時間(> 24小時)。

不知道這個過程是否可以加速?

我相信你的桌子會被鎖定。 我遇到了同樣的問題,發現可以很快刪除10k記錄。 所以你可能想編寫一個簡單的腳本/程序,它將按塊刪除記錄。

   DELETE FROM fuelinjection_stroke WHERE DBID < 1000000 LIMIT 10000;

並繼續執行它直到刪除所有內容

你是否被剝奪了空間? 停工時間不可能嗎?

如果沒有,您可以適應新的INT列長度1並將其默認為1表示“活動”(或任何術語),0表示“非活動”。 實際上,如果需要,你可以使用0到9作為10種不同的狀態。

添加這個新列將花費很多時間,但是一旦結束,只要你從PRIMARY(就像你使用DELETE一樣)執行它,你的UPDATE應該是閃電般的快速,並且你沒有索引這個新列。

InnoDB在如此龐大的表上刪除這么長時間的原因是因為群集索引。 它根據您的PRIMARY(或者它找到的第一個UNIQUE ......或者無法找到PRIMARY或UNIQUE的感覺)對您的表進行物理排序,因此當您拉出一行時,它會在物理上重新排序您的整個表格用於速度和碎片整理的磁盤。 所以不是DELETE花了這么長時間。 刪除該行后的物理重新排序。

當您使用默認值創建新的INT列時,空間將被填充,因此當您更新它時,不需要在您的巨大表格中進行物理重新排序。

我不確定你的模式到底是什么,但是使用列的行的狀態要比DELETEing快得多; 但是,它需要更多的空間。

嘗試設置值:

innodb_flush_log_at_trx_commit=2
innodb_flush_method=O_DIRECT (for non-windows machine)
innodb_buffer_pool_size=25GB (currently it is close to 21GB)
innodb_doublewrite=0
innodb_support_xa=0
innodb_thread_concurrency=0...1000 (try different values, beginning with 200)

參考文獻:

MySQL文檔用於描述不同的變量。

MySQL服務器設置調整

MySQL性能優化基礎知識

http://bugs.mysql.com/bug.php?id=28382

你有什么指數?

我認為你的問題是刪除是在每次迭代時重建索引。

如果有的話,我會刪除索引,執行刪除操作,然后重新添加索引。 它會快得多,(我想)。

我遇到了同樣的問題,我的表有幾個索引,我不想丟棄和重新創建。 所以我做了以下事情:

create table keepers
select * from origTable where {clause to retrieve rows to preserve};
truncate table origTable;
insert into origTable null,keepers.col2,...keepers.col(last) from keepers;
drop table keepers;

大約3分鍾內處理了大約220萬行。

您的數據庫可能正在檢查需要在外鍵中修改的記錄(級聯,刪除)。

但是I-Conica的答案是一個好點(+1)。 在完成100000次期間刪除單個記錄並更新大量索引的過程效率低下。 只需刪除索引,刪除所有記錄並再次創建。

當然,檢查數據庫中是否存在任何類型的鎖定。 一個用戶或應用程序可以鎖定記錄或表,您的查詢將等待用戶釋放資源或達到超時。 檢查數據庫是否正在執行實際工作或只是等待的一種方法是將連接設置--innodb_lock_wait_timeout參數設置為幾秒鍾。 如果它至少失敗,你知道查詢是正常的,你需要找到並重新發布該鎖。 鎖的示例是從XXX中選擇*用於更新和未通信的事務。

對於這樣的長桌,我寧願使用MYISAM,特別是如果不需要很多交易的話。

我不知道確切的問題。 但是寫另一種刪除這些行的方法,請試試這個。

delete from fuelinjection_stroke where DBID in
(
    select top 1000000 DBID  from fuelinjection_stroke 
    order by DBID asc
)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM