[英]How can I insert rows into mysql table faster using python?
我正在嘗試尋找一種更快的方法將數據插入表中,該表最終將超過1億行,我將代碼運行了近24小時,而該表目前僅輸入了900萬行,並且仍在進展。
我的代碼當前一次讀取300個csv文件,並將數據存儲在一個列表中,對重復的行進行過濾,然后使用for循環將一個條目作為一個元組放置在列表中,並在一個表中更新一個元組時間。 這種方法花費的時間太長,有沒有辦法讓我批量插入所有行? 我嘗試過在線查找,但是我正在閱讀的方法似乎對我的情況沒有幫助。
非常感謝,
大衛
import glob
import os
import csv
import mysql.connector
# MYSQL logon
mydb = mysql.connector.connect(
host="localhost",
user="David",
passwd="Sword",
database="twitch"
)
mycursor = mydb.cursor()
# list for strean data file names
streamData=[]
# This function obtains file name list from a folder, this is to open files
in other functions
def getFileNames():
global streamData
global topGames
# the folders to be scanned
#os.chdir("D://UG_Project_Data")
os.chdir("E://UG_Project_Data")
# obtains stream data file names
for file in glob.glob("*streamD*"):
streamData.append(file)
return
# List to store stream data from csv files
sData = []
# Function to read all streamData csv files and store data in a list
def streamsToList():
global streamData
global sData
# Same as gamesToList
index = len(streamData)
num = 0
theFile = streamData[0]
for x in range(index):
if (num == 301):
filterStreams(sData)
num = 0
sData.clear()
try:
theFile = streamData[x]
timestamp = theFile[0:15]
dateTime = timestamp[4:8]+"-"+timestamp[2:4]+"-"+timestamp[0:2]+"T"+timestamp[9:11]+":"+timestamp[11:13]+":"+timestamp[13:15]+"Z"
with open (theFile, encoding="utf-8-sig") as f:
reader = csv.reader(f)
next(reader) # skip header
for row in reader:
if (row != []):
col1 = row[0]
col2 = row[1]
col3 = row[2]
col4 = row[3]
col5 = row[4]
col6 = row[5]
col7 = row[6]
col8 = row[7]
col9 = row[8]
col10 = row[9]
col11 = row[10]
col12 = row[11]
col13 = dateTime
temp = col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11, col12, col13
sData.append(temp)
except:
print("Problem file:")
print(theFile)
print(num)
num +=1
return
def filterStreams(self):
sData = self
dataSet = set(tuple(x) for x in sData)
sData = [ list (x) for x in dataSet ]
return createStreamDB(sData)
# Function to create a table of stream data
def createStreamDB(self):
global mydb
global mycursor
sData = self
tupleList = ()
for x in sData:
tupleList = tuple(x)
sql = "INSERT INTO streams (id, user_id, user_name, game_id, community_ids, type, title, viewer_count, started_at, language, thumbnail_url, tag_ids, time_stamp) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
val = tupleList
try:
mycursor.execute(sql, val)
mydb.commit()
except:
test = 1
return
if __name__== '__main__':
getFileNames()
streamsToList()
filterStreams(sData)
如果某些行成功但有些行失敗,是否要讓數據庫處於損壞狀態? 如果否,請嘗試退出循環。 像這樣:
for x in sData:
tupleList = tuple(x)
sql = "INSERT INTO streams (id, user_id, user_name, game_id, community_ids, type, title, viewer_count, started_at, language, thumbnail_url, tag_ids, time_stamp) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
val = tupleList
try:
mycursor.execute(sql, val)
except:
# do some thing
pass
try:
mydb.commit()
except:
test = 1
如果沒有的話。 嘗試直接將cvs
文件加載到mysql中。
LOAD DATA INFILE "/home/your_data.csv"
INTO TABLE CSVImport
COLUMNS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 LINES;
另外,使您更清晰。 如果您堅持使用python,我已經定義了三種插入數據的方法,因為您需要對數據進行一些處理。
不好的方法
In [18]: def inside_loop():
...: start = time.time()
...: for i in range(10000):
...: mycursor = mydb.cursor()
...: sql = "insert into t1(name, age)values(%s, %s)"
...: try:
...: mycursor.execute(sql, ("frank", 27))
...: mydb.commit()
...: except:
...: print("Failure..")
...: print("cost :{}".format(time.time() - start))
...:
時間成本:
In [19]: inside_loop()
cost :5.92155909538269
好吧
In [9]: def outside_loop():
...: start = time.time()
...: for i in range(10000):
...: mycursor = mydb.cursor()
...: sql = "insert into t1(name, age)values(%s, %s)"
...: try:
...: mycursor.execute(sql, ["frank", 27])
...: except:
...: print("do something ..")
...:
...: try:
...: mydb.commit()
...: except:
...: print("Failure..")
...: print("cost :{}".format(time.time() - start))
時間成本:
In [10]: outside_loop()
cost :0.9959311485290527
也許,還有更好的方法,甚至最好的方法。 (即,使用pandas
處理數據。並嘗試重新設計表...)
您可能喜歡我的演示文稿, 快速加載數據! 在其中,我比較了插入大數據的不同方法,並進行了基准測試,以了解哪種方法最快。
一次插入一行,為每一行提交一個事務,這是最差的操作方式。
使用LOAD DATA INFILE是最快的。 盡管您需要對默認的MySQL實例進行一些配置更改才能使其正常工作。 閱讀有關選項secure_file_priv
和local_infile
的MySQL文檔。
即使不使用LOAD DATA INFILE,您也可以做得更好。 您可以為每個INSERT插入多行,並且可以為每個事務執行多個INSERT語句。
不過,我不會嘗試在單個事務中插入全部1億行。 我的習慣是每10,000行提交一次。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.