2017-05-26 36 views
1

私のMySQLのテーブルのスキーマは次のとおりです。なぜ 'executemany'は 'IN'クエリを実行するのと比べて遅いのですか?

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,...)はあなたがIDのシーケンスを持っている場合は、さらに良いがWHERE id BETWEEN 1 and 1000を言うことだろうはるかに効率的UPDATE;UPDATE;UPDATE...

を超えています。これは、各行を最初から検索するのではなく、単に行をスキャンできるからです。 (私はidがインデックスされていると仮定しています(PRIMARY KEYと思われます)。

また、各挿入/更新/削除を独自の「トランザクション」にする設定で実行している可能性があります。これにより、各UPDATEに多くのオーバーヘッドが追加されます。そして、この場合はおそらく望ましくないでしょう。 1000行の更新全体をアトミックにしたいと思っています。

ボトムライン:executemanyは、(a)INSERTsまたは(b)個別に実行する必要があるステートメントのみを使用してください。

+0

こちらの参考資料はありますか? –

+0

https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-executemany.htmlさらに、行間を読む。 –

関連する問題