python+mysql:實現一千萬條數據插入數據庫


作業要求

構建一個關系模式和課本中的關系movies(title,year,length,movietype,studioname,producerC)一樣的關系,名稱自定,在這個關系中插入1000萬條記錄。

注:關系movies的主鍵為(title,year)

要求如下:

  1. 在盡可能短的時間內完成;
  2. 只允許使用原生的SQL,不允許將SQL作為嵌入語言,也不允許使用其他語言如C#、Python等來完成;
  3. 提交你的詳細解決方案和結果。

分析

查資料得知

  • 可以將多條insert語句合並為一句,即一條insert語句插入多個元組
  • 可以通過事務,減少每條insert語句都建立新事務帶來的時空消耗
  • 可以通過load data infile將文件中的數據導入mysql,似乎很快的樣子

雖然第三種似乎很快,但在此我采用了前兩種方法,通過合並+事務實現。

我通過python模擬生成(只改變主鍵中的year,以生成不同元組)1千萬條記錄,將其組織為\(10\times100\times10000\)條記錄添加進movies,分成10個事務,每個事務里有100條insert語句,每條insert語句插入10000個元組。

實現

實現思路如下:

  1. 復制原數據庫moviedbnewmoviedb
  2. 設置max_allowed_packet,以保證一條insert語句可以插入足夠多的元組
  3. 用python生成一條一次插入10000個元組的insert語句
  4. 用python生成一個包含100條insert語句的事務,保存至sql文件
  5. 用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/

歡迎討論和交流!



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM