データベースの訂正スクリプトの性能の最適化の2つ:不要なクエリと一括挿入SQLを削除します。
6990 ワード
最近では、複数のデータベースを統合するスクリプトをメインデータベースに統合します。以下はデータ訂正スクリプトを作成する際に犯したミスです。
不必要なクエリ
次の文を見てください。
regiondb = db.Houyiregiondb()
houyidb = db.Houyidb(read_only=False)
regiondbRet = regiondb.query(vmmacsFromRegiondbSql)
houyidbRet = houyidb.query(vmmacsFromHouyidbSql)
if len(regiondbRet) == 0:
return
本来の意味は、housidbとhouyire giondbそれぞれのレコードを取り出して、それを対比するためである。しかし、ここで何も考えずにhousidbで調べた語句を早まってしまい、結果としてhousidbで調べられてしまうかもしれません。 housyidb.query(vmmacs Froom HouyidbSql)は不必要なクエリとなります。このクエリが多くのデータを引き出すと、無駄になります。バイトはお金です。今のプログラマーは、昔のプログラマーのようにけちにしなくてもいいかもしれません。修復方法は簡単です。語句の順序を置き換えればいいです。 regiondb = db.Houyiregiondb()
regiondbRet = regiondb.query(vmmacsFromRegiondbSql)
if len(regiondbRet) == 0:
regiondb.close()
return
houyidb = db.Houyidb(read_only=False)
houyidbRet = houyidb.query(vmmacsFromHouyidbSql)
教訓: プログラムを書くには,思慮の余地がない。ロックタイムアウト
, Lock wait timeout exceeded; try restarting transaction 。
, insert X delete from X where ... 。 insert , delete X 。 insert X , 1 , innodb_lock_wait_timeout = 50s ( show variables like "%timeout%";) delete X 。 , : insert X , delete X , 50s 。
sql 。 : , 1000 。 :
def divideIntoGroups(allTuples, numPerGroup=1000):
'''
divide tuples into group of tuples ;
each group has no more than numPerGroup tuples
default value of numPerGroup is 1000
'''
groups = []
totalNum = len(allTuples)
if totalNum <= numPerGroup:
groups.append(allTuples)
return groups
start = 0
eachEnd = start + numPerGroup
while start < totalNum:
groups.append(allTuples[start:eachEnd])
start += numPerGroup
eachEnd = start + numPerGroup
if eachEnd >= totalNum:
eachEnd = totalNum
return groups
def insertManyMany(insertSql, allTuples, db):
'''
insert many many records , usually more than 10000
insert 1000 once and insert (len/1000+1) times
'''
groups = divideIntoGroups(allTuples)
count = 0
for groupTuples in groups:
affectRows = db.executemany(insertSql, groupTuples)
if affectRows:
count += affectRows
db.commit()
needInsertNum = len(allTuples)
isPassedMsg = ('OK' if needInsertNum==count else 'SOME ERROR')
printAndLog("Need insert %d records, and actual %d. %s" % (needInsertNum, count, isPassedMsg))
调用方法如下:
insertSql = "insert into student (name, age) value (%s, %s) "
allTuples = [("zhang", 20), ("qian", 25), ("wang", 23), ... , ("liu", 26)]
insertManyMany(insertSql, allTuples, db)
。 32000 18s, 2-3s , 129968 67s , 12-15s. , , 。