2017-05-26 34 views
1

我的MySQL表架構是:與只做一個'IN'查詢相比,爲什麼'executemany'這麼慢?

CREATE DATABASE test_db; 
USE test_db; 
CREATE TABLE test_table (
    id INT AUTO_INCREMENT, 
    last_modified DATETIME NOT NULL, 
    PRIMARY KEY (id) 
) ENGINE=InnoDB; 

當我運行下面的基準腳本,我得到:

B1:20.5559301376

B2:0.504406929016

from timeit import timeit 
import MySQLdb 

ids = range(1000) 

query_1 = "update test_table set last_modified=UTC_TIMESTAMP() where id=%(id)s" 
query_2 = "update test_table set last_modified=UTC_TIMESTAMP() where id in (%s)" % ", ".join(('%s',) * len(ids)) 

db = MySQLdb.connect(host="localhost", user="some_user", passwd="some_pwd", db="test_db") 

def b1(): 
    curs = db.cursor() 
    curs.executemany(query_1, ids) 
    db.close() 

def b2(): 
    curs = db.cursor() 
    curs.execute(query_2, ids) 
    db.close() 

print "b1: %s" % str(timeit(lambda:b1(), number=30)) 
print "b2: %s" % str(timeit(lambda:b2(), number=30)) 

01爲什麼會有這麼大的差異?和IN子句?

我使用Python 2.6.6和MySQL-python 1.2.3。

我能找到的唯一相關問題是 - Why is executemany slow in Python MySQLdb?,但這並不是我真正想要的。

+0

關鍵的區別是'executemany'不能保證單個數據庫往返。這是'盡最大努力',其中努力往往不是很大,而'實際單一語句往返'卻不是那麼好。另請參閱https://stackoverflow.com/questions/4101076/executemany-confusion – pvg

回答

0

executemany反覆地來回MySQL服務器,然後需要解析查詢,執行它並返回結果。這可能比單個SQL語句中的所有內容慢10倍,即使它比較複雜。

但是,對於INSERT,this表示它會爲您做出智能的事情併爲您構建多行INSERT,從而提高效率。

因此,IN(1,2,3,...)UPDATE;UPDATE;UPDATE...

高效得多。如果你有ID的序列,那麼就再好不過是說WHERE id BETWEEN 1 and 1000。這是因爲它可以簡單地掃描行而不是從頭開始查找每一行。 (我假設id被索引,可能是PRIMARY KEY。)

另外,您可能正在使用將每個插入/更新/刪除操作設置爲自己的「事務」的設置運行。這爲每個UPDATE增加了很多開銷。在這種情況下,這可能是不可取的。我懷疑你想要整個1000行更新是原子的。

底線:僅對(a)INSERTs使用executemany或(b)必須單獨運行的聲明。

+0

你有任何這樣的參考? –

+0

https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-executemany.html,以及行之間的閱讀。 –

相關問題