mysql 优化配置 大批量数据插入_[译] MySQL 最佳实践 —— 高效插入数据
當你需要在 MySQL 數據庫中批量插入數百萬條數據時,你就會意識到,逐條發送 INSERT 語句并不是一個可行的方法。
MySQL 文檔中有些值得一讀的 INSERT 優化技巧。
在這篇文章里,我將概述高效加載數據到 MySQL 數據庫的兩大技術。
LOAD DATA INFILE
如果你正在尋找提高原始性能的方案,這無疑是你的首選方案。LOAD DATA INFILE 是一個專門為 MySQL 高度優化的語句,它直接將數據從 CSV / TSV 文件插入到表中。
有兩種方法可以使用 LOAD DATA INFILE。你可以把數據文件拷貝到服務端數據目錄(通常 /var/lib/mysql-files/),并且運行:
LOAD DATA INFILE '/path/to/products.csv' INTO TABLE products;這個方法相當麻煩,因為你需要訪問服務器的文件系統,為數據文件設置合適的權限等。
好消息是,你也能將數據文件存儲在客戶端,并且使用 LOCAL 關鍵詞:
LOAD DATA LOCAL INFILE '/path/to/products.csv' INTO TABLE products;在這種情況下,從客戶端文件系統中讀取文件,將其透明地拷貝到服務端臨時目錄,然后從該目錄導入??偠灾?#xff0c;這幾乎與直接從服務器文件系統加載文件一樣快,不過,你需要確保服務器啟用了此 選項。
LOAD DATA INFILE 有很多可選項,主要與數據文件的結構有關(字段分隔符、附件等)。請瀏覽 文檔 以查看全部內容。
雖然從性能角度考慮, LOAD DATA INFILE 是最佳選項,但是這種方式需要你先將數據以逗號分隔的形式導出到文本文件中。如果你沒有這樣的文件,你就需要花費額外的資源來創建它們,并且可能會在一定程度上增加應用程序的復雜性。幸運的是,還有一種另外的選擇。
擴展的插入語句(Extended inserts)
一個典型的 INSERT SQL 語句是這樣的:
INSERT INTO user (id, name) VALUES (1, 'Ben');extended INSERT 將多條插入記錄聚合到一個查詢語句中:
INSERT INTO user (id, name) VALUES (1, 'Ben'), (2, 'Bob');關鍵在于找到每條語句中要插入的記錄的最佳數量。沒有一個放之四海而皆準的數字,因此,你需要對數據樣本做基準測試,以找到性能收益的最大值,或者在內存使用和性能方面找到最佳折衷。
為了充分利用 extended insert,我們還建議:
- 使用預處理語句
- 在事務中運行該語句
基準測試
我要插入 120 萬條記錄,每條記錄由 6 個 混合類型數據組成,平均每條數據約 26 個字節大小。我使用了兩種常見的配置進行測試:
- 客戶端和服務端在同一機器上,通過 UNIX 套接字進行通信
- 客戶端和服務端在不同的機器上,通過延遲非常低(小于 0.1 毫秒)的千兆網絡進行通信
作為比較的基礎,我使用 INSERT ... SELECT 復制了該表,這個操作的性能表現為每秒插入 313,000 條數據。
LOAD DATA INFILE
令我吃驚的是,測試結果證明 LOAD DATA INFILE 比拷貝表更快:
- LOAD DATA INFILE:每秒 377,000 次插入
- LOAD DATA LOCAL INFILE 通過網絡:每秒 322,000 次插入
這兩個數字的差異似乎與從客戶端到服務端傳輸數據的耗時有直接的關系:數據文件的大小為 53 MB,兩個基準測試的時間差了 543 ms,這表示傳輸速度為 780 mbps,接近千兆速度。
這意味著,很有可能,在完全傳輸文件之前,MySQL 服務器并沒有開始處理該文件:因此,插入的速度與客戶端和服務端之間的帶寬直接相關,如果它們不在同一臺機器上,考慮這一點則非常重要。
Extended inserts
我使用 BulkInserter 來測試插入的速度,BulkInserter 是我編寫的 開源庫 PHP 類的一部分,每個查詢最多插入 10,000 條記錄:
正如我們所看到的,隨著每條查詢插入數的增長,插入速度也會迅速提高。與逐條插入速度相比,我們在本地主機上性能提升了 6 倍,在網絡主機上性能提升了 17 倍:
- 在本地主機上每秒插入數量從 40,000 提升至 247,000
- 在網絡主機上每秒插入數量從 1,2000 提升至 201,000
這兩種情況都需要每個查詢大約 1,000 個插入來達到最大吞吐量。但是每條查詢 40 個插入就足以在本地主機上達到 90% 的吞吐量,這可能是一個很好的折衷。還需要注意的是,達到峰值之后,隨著每個查詢插入數量的增加,性能實際上是會下降。
extended insert 的優勢在網絡連接的情況下更加明顯,因為連續插入的速度取決于你的網絡延遲。
max sequential inserts per second ~= 1000 / ping in milliseconds客戶端和服務端之間的延遲越高,你從 extended insert 中獲益越多。
結論
不出所料,LOAD DATA INFILE 是在單個連接上提升性能的首選方案。它要求你準備格式正確的文件,如果你必須先生成這個文件,并/或將其傳輸到數據庫服務器,那么在測試插入速度時一定要把這個過程的時間消耗考慮進去。
另一方面,extended insert 不需要臨時的文本文件,并且可以達到相當于 LOAD DATA INFILE 65% 的吞吐量,這是非常合理的插入速度。有意思的是,無論是基于網絡還是本地主機,聚集多條插入到單個查詢總是能得到更好的性能。
如果你決定開始使用 extended insert,一定要先用生產環境的數據樣本和一些不同的插入數來測試你的環境,以找出最佳的數值。。
在增加單個查詢的插入數的時候要小心,因此它可能需要:
- 在客戶端分配更多的內存
- 增加 MySQL 服務器的 max_allowed_packet 參數配置。
最后,值得一提的是,根據 Percona 的說法,你可以使用并發連接、分區以及多個緩沖池,以獲得更好的性能。更多信息請查看 他們博客的這篇文章。
基準測試運行在裝有 Centos 7 和 MySQL 5.7 的裸服務器上,它的主要硬件配置有 Xeon E3 @3.8 GHz 處理器,32 GB RAM 和 NVMe SSD。MySQL 的基準表使用 InnoBD 存儲引擎。
基準測試的源代碼保存在 gist 上,結果圖保存在 plot.ly 上。
- 原文地址:High-speed inserts with MySQL
- 原文作者:Benjamin Morel
- 譯文出自:掘金翻譯計劃
- 譯者:司徒公子
- 校對者:GJXAIOU、QinRoc
總結
以上是生活随笔為你收集整理的mysql 优化配置 大批量数据插入_[译] MySQL 最佳实践 —— 高效插入数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: desk98.exe是病毒进程吗 des
- 下一篇: 5万元理财可以买什么理财产品?一年可以赚