作業要求
構建一個關系模式和課本中的關系movies(title,year,length,movietype,studioname,producerC)
一樣的關系,名稱自定,在這個關系中插入1000萬條記錄。
注:關系movies
的主鍵為(title,year)
。
要求如下:
- 在盡可能短的時間內完成;
- 只允許使用原生的SQL,不允許將SQL作為嵌入語言,也不允許使用其他語言如C#、Python等來完成;
- 提交你的詳細解決方案和結果。
分析
查資料得知
- 可以將多條insert語句合並為一句,即一條insert語句插入多個元組
- 可以通過事務,減少每條insert語句都建立新事務帶來的時空消耗
- 可以通過
load data infile
將文件中的數據導入mysql,似乎很快的樣子
雖然第三種似乎很快,但在此我采用了前兩種方法,通過合並+事務實現。
我通過python模擬生成(只改變主鍵中的year,以生成不同元組)1千萬條記錄,將其組織為\(10\times100\times10000\)條記錄添加進movies
,分成10個事務,每個事務里有100條insert語句,每條insert語句插入10000個元組。
實現
實現思路如下:
- 復制原數據庫
moviedb
至newmoviedb
- 設置max_allowed_packet,以保證一條insert語句可以插入足夠多的元組
- 用python生成一條一次插入10000個元組的insert語句
- 用python生成一個包含100條insert語句的事務,保存至sql文件
- 用navicat運行該sql文件
至此就可以實現一百萬條記錄的插入了(我的電腦耗時327s?好像很慢!?)
之后再套一層循環就可以繼續完成1千萬條記錄的插入了。
下面給出可能用到的步驟(如未說明,代碼默認為控制行或者mysql環境下的命令):
復制數據庫
創建新數據庫newmoviedb
登錄並創建數據庫:
mysql -u root -p
CREATE DATABASE `newmoviedb` DEFAULT CHARACTER SET UTF8 COLLATE UTF8_GENERAL_CI;
復制moviedb至newmoviedb
復制數據庫
mysqldump moviedb -u root -pchouxianyu --add-drop-table | mysql newmoviedb -u root -pchouxianyu
上面chouxianyu
是我的mysql密碼
進入newmoviedb
use newmoviedb;
設置max_allowed_packet
設置max_allowed_packet為100M
set global max_allowed_packet = 100*1024*1024;
刪除movies中所有元素(調試用)
delete from movies;
生成一條insert語句
下邊是insert.py
insertStr = "INSERT INTO movies(title,year,length,movietype,studioname,producerC) VALUES"
value1_str = "('mymovietitle',"
# j
value2_str = ",120,'sciFic','MGM',100)"
# ,;
num_value = 10000
f = open(r'C:\Users\Cxy\Documents\Navicat\MySQL\Servers\MySQL\newmoviedb\insertRow.sql', 'w') # 清空文件內容再寫
f.write(insertStr)
for j in range(1, num_value):
f.write(value1_str)
f.write(str(j))
f.write(value2_str)
f.write(',')
f.write(value1_str)
f.write(str(num_value))
f.write(value2_str)
f.write(';')
f.close()
生成一個事務
以下是transaction.py
transaction_begin_str = "START TRANSACTION;\n"
transaction_end_str = "COMMIT;\n"
insertStr = "INSERT INTO movies(title,year,length,movietype,studioname,producerC) VALUES"
value1_str = "('mymovietitle',"
# j
value2_str = ",120,'sciFic','MGM',100)"
# ,;
num_value = 10000
num_sql = 100
# 打開文件
f = open(r'C:\Users\Cxy\Documents\Navicat\MySQL\Servers\MySQL\newmoviedb\transaction.sql', 'w') # 清空文件內容再寫
# 將SQL語句寫入文件
f.write(transaction_begin_str)
for i in range(1, num_sql+1):
f.write(insertStr)
for j in range(1, num_value):
f.write(value1_str)
f.write(str(i*num_value*10+j))
f.write(value2_str)
f.write(',')
f.write(value1_str)
f.write(str(i*num_value*10+num_value))
f.write(value2_str)
f.write(';\n')
f.write(transaction_end_str)
# 關閉文件
f.close()
參考鏈接
https://www.cnblogs.com/freefei/p/7679991.html
https://blog.csdn.net/qq_22855325/article/details/76087138
https://blog.csdn.net/weixin_44595372/article/details/88723191
https://zhidao.baidu.com/question/185665472.html
https://www.cnblogs.com/zhangjpn/p/6231662.html
https://www.cnblogs.com/wangcp-2014/p/8038683.html
https://blog.csdn.net/gb4215287/article/details/82669785
作者:@臭咸魚
轉載請注明出處:https://www.cnblogs.com/chouxianyu/
歡迎討論和交流!