日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

背景

MySQL在插入數據的時候,應該怎么插入速度最快,效率最高?

我們經常使用的插入方式有如下幾種:

  • 第一種:直接一行一個insert語句,如下所示:
insert into user(name, birthday) values('A','19950902');
...... /*此處省略*/
insert into user(name, birthday) values('C','19950904');
  • 第二種:使用begin和commit事務包裹起來的每一行一個插入語句。
begin;
insert into user(name, birthday) values('A','19950902');
...... /*此處省略*/
insert into user(name, birthday) values('C','19950904');
commit;
  • 第三種:values關鍵字后面跟著很多行數據,一起批量插入。
insert into user(name, birthday) values('A','19950902'),('B','19950903'),('C','19950904');
...... /*此處省略*/
insert into user(name, birthday) values('A','19950902'),('B','19950903'),('C','19950904');
  • 第四種:使用begin和commit事務包裹起來的批量插入的語句。
begin;
insert into user(name, birthday) values('A','19950902'),('B','19950903'),('C','19950904');
...... /*此處省略*/
insert into user(name, birthday) values('A','19950902'),('B','19950903'),('C','19950904');
end;

以上幾種插入的語句,哪個SQL更快?下面讓我們驗證一下。

環境準備

準備表

我們在本地的MySQL中準備4張表,這樣可以避免網絡延遲導致的測試結果不準確的因素,本地直接連接MySQL數據庫,網絡因素就可以排除了。這四張表結構一樣,然后針對這4張表,我們分別使用前面提到的4張插入數據的方式,分別測試。

4張表的結構如下,表名稱不同,表結構一樣。

CREATE TABLE `user_info_1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(64) DEFAULT NULL,
  `age` tinyint(4) DEFAULT NULL,
  `cellphone` varchar(11) DEFAULT NULL,
  `address` varchar(128) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='第一種插入方式使用的表';

CREATE TABLE `user_info_2` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(64) DEFAULT NULL,
  `age` tinyint(4) DEFAULT NULL,
  `cellphone` varchar(11) DEFAULT NULL,
  `address` varchar(128) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='第二種插入方式使用的表';

CREATE TABLE `user_info_3` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(64) DEFAULT NULL,
  `age` tinyint(4) DEFAULT NULL,
  `cellphone` varchar(11) DEFAULT NULL,
  `address` varchar(128) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='第三種插入方式使用的表';

CREATE TABLE `user_info_1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(64) DEFAULT NULL,
  `age` tinyint(4) DEFAULT NULL,
  `cellphone` varchar(11) DEFAULT NULL,
  `address` varchar(128) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='第四種插入方式使用的表';

主備數據

初始化數據的時候,大家可以參考這個存儲過程,這個存儲過程的作用就是在user_info表中生成指定行數的測試數據,該存儲過程如下:

CREATE PROCEDURE `initial_user_info`(max_id int)
begin
    declare m int default 0;
    declare _username varchar(64) default '';
    declare _age int default 0;
    declare _cellphone varchar(11) default '';
    declare _address varchar(255) default '';
		
		start transaction;
		
			while m < max_id do
					set m = m + 1;
					set _username = substring( uuid(), 1, floor(8 + rand() * (29)));
					set _age = floor(18 + rand() * (43));
					set _cellphone = substr(rand(),-11);
					set _address = concat(substring( uuid(), 1, floor(8 + rand() * (29))), substring( uuid(), 1, floor(8 + rand() * (29))));
					insert into user_info (user_name, age, cellphone, address) values(_username, _age, _cellphone, _address);
			end while;
		
		commit;

end

如下的SQL是向user_info表中插入24W測試數據。

CREATE TABLE `user_info` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(64) DEFAULT NULL,
  `age` tinyint(4) DEFAULT NULL,
  `cellphone` varchar(11) DEFAULT NULL,
  `address` varchar(128) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用于存儲生成的測試數據的表';

call initial_user_info(240000);

當user_info表中的數據準備好之后,我們可以把這表中的數據用數據庫客戶端工具導出來,導出的時候可以導出兩種格式:一種是一行一行的insert語句,一種是批量insert的語句。基于導出來的這兩種SQL文件,我們再手動patch成下面四個SQL文件。

準備待導入的SQL文件的時候,我們按照前面提到的4種方式,分別為user_info_1.sql、user_info_2.sql、user_info_3.sql、user_info_4.sql四個SQL文件,每一個文件中待導入的記錄數都是24W行數據。它們里面的內容也是按照四中插入方式準備的。

  • 第一種,user_info_1.sql文件。里面的內容是一行一行的insert語句,每一行數據一個insert。沒有使用事務begin和commit包裹起來。
  • 第二種,user_info_2.sql文件。里面的內容是一行一行的insert語句,每一行數據一個insert。與第一個SQL文件的區別是,在文件第一行有begin,在文件的最后一行有commit。文件中的所有的語句使用一個事務begin和commit包裹起來。
  • 第三種,user_info_3.sql文件。里面的內容是一行一行的insert語句,每一個insert語句后面跟著大概700~800個values值。是批量插入的一種方式,但是所有的批量插入的語句,沒有使用事務begin和commit包裹起來。
  • 第四種,user_info_4.sql文件。里面的內容是一行一行的insert語句,每一個insert語句后面跟著大概700~800個values值。是批量插入的一種方式,但是文件的開頭是begin,文件的最后一行是commit。所有的批量插入的語句,使用一個事務begin和commit包裹起來。

為了方便記錄每一個SQL導入消耗的實際,我們使用一個簡單的shell腳本來導入SQL文件,腳本內如下:

echo "`date '+%Y-%m-%d %H:%M:%S'`,開始導入..."
mysql -uroot -proot insert_by_batch_test < $1
echo "`date '+%Y-%m-%d %H:%M:%S'`,導入結束..."

執行導入的結果如下:

?  ~ ./mysql_import.sh ~/Downloads/user_info_1.sql
2021-07-16 15:08:15,開始導入...
mysql: [Warning] Using a password on the command line interface can be insecure.
2021-07-16 15:09:33,導入結束...
?  ~ #耗時 78s
?  ~
?  ~ ./mysql_import.sh ~/Downloads/user_info_2.sql
2021-07-16 15:10:24,開始導入...
mysql: [Warning] Using a password on the command line interface can be insecure.
2021-07-16 15:11:20,導入結束...
?  ~ #耗時 56s
?  ~
?  ~ ./mysql_import.sh ~/Downloads/user_info_3.sql
2021-07-16 15:11:37,開始導入...
mysql: [Warning] Using a password on the command line interface can be insecure.
2021-07-16 15:11:39,導入結束...
?  ~ #耗時 2s
?  ~
?  ~ ./mysql_import.sh ~/Downloads/user_info_4.sql
2021-07-16 15:11:46,開始導入...
mysql: [Warning] Using a password on the command line interface can be insecure.
2021-07-16 15:11:47,導入結束...
?  ~ #耗時 1s
?  ~

通過上面的實驗過程可以發現,第一種導入的效率最差,最后一種導入的效率最高。四種導入方式的效率為:

第一種方式 < 第二種方式 < 第三種方式 < 第四種方式

總結

  • 第一種每一次都需要進行語法解析和語法判斷,數據量特別大的時候每次解析的時間累計起來就很耗時,這是它慢的主要原因。
  • 第二種相對一對一種有一些優化,主要是對日志的操作有原先的一個SQL語句一個事務日志改為所有的SQL語句一個事務日志,這里的日志主要是binlog日志和回滾日志。
  • 第三種執行效率高的主要緣由是合并了SQL語句,采用批量的插入方式,降低了SQL語句解析的次數。此時的日志量binlog日志和回滾日志也合并在一起,下降日志刷盤的數據量和頻率,從而提升效率。
  • 和第三種相比,這種方式把所有的操作合并為一個事務,日志合并后,降低了日志刷盤次數。所以此時效率更高。

所以在初始化一些數據的時候,我們盡量使用批量insert的方式,與此同時在批量insert語句前后使用事務包裹起來。當然事務包裹的SQL語句的大小也要合適,不能無限制地使用一個特別大的事務,這樣效率也不高。

分享到:
標簽:MySQL
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定