MySQL利用存儲過程批量插入數據

時間問題,sql代碼是自己寫的,文本描述是複製的,內容有差異的請自己辨別

首先我是簡單的寫了一個mysql的循環插入數據的SP,具體如下:

DROP PROCEDURE IF EXISTS prod_dt;
CREATE PROCEDURE prod_dt()
BEGIN
DECLARE i int;
set i = 0;
WHILE i<1000000 DO
	INSERT INTO `topic`( `name`, `image`, `anwer_a`, `anwer_a_image`, `anwer_b`, `anwer_b_image`, `answer_c`, `answer_c_image`, `anwer_d`, `answer_d_image`, `true_answer`, `author_id`, `difficulty`, `topic_type`, `tag_ids`, `show_id`, `show_detail_id`, `status`, `topic_introduce`, `use_status`) VALUES ( '題目名稱', '題目圖片', '答案a', '答案a圖片', '答案b', '答案b圖片', '答案c', '答案c圖片', '答案d', '答案d圖片', NULL, 1, 1, 1, '3', 3, 1, 2, '題目釋義', 1);
SET i = i+1;
END WHILE;
END;

call prod_dt();

這是插入100W數據的過程和結果,可以看到是換了55min +20S約3320秒(約300rows/s),看到之後我是隻崩潰,就在網上查了些提速的方法:

最快的當然是直接 copy 數據庫表的數據文件(版本和平臺最好要相同或相似);1. 設置 innodb_flush_log_at_trx_commit = 0 ,相對於 innodb_flush_log_at_trx_commit = 1 可以十分明顯的提升導入速度;2. 使用 load data local infile 提速明顯;3. 修改參數 bulk_insert_buffer_size, 調大批量插入的緩存;4. 合併多條 insert 爲一條: insert into t values(a,b,c), (d,e,f) ,5. 手動使用事物

在這裏插入圖片描述
而我創建的是Innodb類型的表,分了128個分區。而我依照以上的方法,設置如下:

DROP PROCEDURE IF EXISTS prod_dt;
CREATE PROCEDURE prod_dt()
BEGIN
DECLARE i int;
set i = 0;
WHILE i<100000 DO
	INSERT INTO `zjc_topic`( `name`, `image`, `anwer_a`, `anwer_a_image`, `anwer_b`, `anwer_b_image`, `answer_c`, `answer_c_image`, `anwer_d`, `answer_d_image`, `true_answer`, `author_id`, `difficulty`, `topic_type`, `tag_ids`, `show_id`, `show_detail_id`, `status`, `topic_introduce`, `use_status`) VALUES ( '題目名稱', '題目圖片', '答案a', '答案a圖片', '答案b', '答案b圖片', '答案c', '答案c圖片', '答案d', '答案d圖片', NULL, 1, 1, 1, '3', 3, 1, 2, '題目釋義', 1);
SET i = i+1;
END WHILE;
END;

TRUNCATE TABLE zjc_topic;

SET SESSION unique_checks=0;
SET SESSION autocommit=0;

call prod_dt();

SET SESSION unique_checks=1;
SET SESSION autocommit=1;

可以明顯的看到插入百萬數據是100S左右,速度提升了33倍之多。

速度是提升了不少,那就加大插入的數據量,提升10倍,即插入千萬的數據量,具體的SP如下:
varchar字段

  • 字段的限制在字段定義的時候有以下規則: a) 存儲限制 varchar 字段是將實際內容單獨存儲在聚簇索引之外,內容開頭用1到2個字節表示實際長度(長度超過255時需要2個字節),因此最大長度不能超過65535。 b) 編碼長度限制 字符類型若爲gbk,每個字符最多佔2個字節,最大長度不能超過32766;   字符類型若爲utf8,每個字符最多佔3個字節,最大長度不能超過21845。   對於英文比較多的論壇 ,使用GBK則每個字符佔用2個字節,而使用UTF-8英文卻只佔一個字節。   若定義的時候超過上述限制,則varchar字段會被強行轉爲text類型,併產生warning。 c) 行長度限制   導致實際應用中varchar長度限制的是一個行定義的長度。 MySQL要求一個行的定義長度不能超過65535。若定義的表長度超過這個值,則提示   ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to    change some columns to TEXT or BLOBs。

在這裏插入圖片描述
再次升級插入的數據量,提升10倍,看插入的時間及佔用的內存,字段的字節同樣爲1000,具體的SP和結果如下:

從上圖可以清楚的看到,插入1億條數據的時間爲5hours +20 min+ 56s=19256s,平均插入的條數爲(5193 rows/s)。根上次插入1千萬條的時間差不多,再看所耗磁盤空間,用了98G的空間,跟上次插入千萬條數據時的(26G-17G=9G)也是成線性關係的。按照本機500G的磁盤空間,存儲1行1K字節大小的數據,本機可以存儲理想極限情況下爲5億條數據,保守爲4~4.5億左右合適,以防其他的應用或者數據庫的UNDO,索引空間佔用。

最後再看一次查詢的時間,上次插入百萬數,查詢數據量的時間
在這裏插入圖片描述
因爲創建了索引,在查百萬級的數據量時,時間是1秒左右,在數據量上升到千萬時,查詢1億5百萬時,時間爲3Min 30S,再插入1億數據,查詢數據量,時間達到27min 43s,可見,不是線性關係,是幾何級增加的。

現在描述集羣環境的測試

集羣:32G內存 ,500G硬盤,3臺虛擬機也就是3個節點:188.188.2.181(主節點,數據節點和SQL節點)、188.188.2.182(數據節點和SQL節點)和188.188.2.183(數據節點和SQL節點)。/root目錄分區磁盤空間200G(原先默認的是50G)、插入的數據量爲8000KW,所佔磁盤空間爲下圖
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章