2016-12-16 43 views
1

我正在使用Connector/Python将许多行插入到mysql中的临时表中。这些行都在列表中。我执行这样的插入:为什么Connector/Python执行优化插入?

cursor = connection.cursor(); 
batch = [[1, 'foo', 'bar'],[2, 'xyz', 'baz']] 
cursor.executemany('INSERT INTO temp VALUES(?, ?, ?)', batch) 
connection.commit() 

我注意到(当然有更多的行)性能非常差。使用SHOW PROCESSLIST,我注意到每个插入都单独执行。但文档https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-executemany.html说这应该优化到1插入。这是怎么回事?

+0

https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html“此方法执行给定的数据库操作(查询或命令)。元组或字典参数绑定到操作中的变量,使用%s或%(name)s参数样式指定变量(即使用格式或pyformat样式),如果multi为True,则execute()返回一个迭代器。没有?在所有的游标api占位符。 – pvg

+0

然而,该声明与'?'完全吻合。我用它是因为其他开发人员在现有代码中使用它。它有点奇怪,它有点作用。 – blueimpb

+0

api本身支持各种占位符,也许某些通用功能在某处捕捉它们?无论哪种方式,您实际上都可以查询占位符的实现本身https://www.python.org/dev/peps/pep-0249/#paramstyle在使用mysql连接器的情况下,应始终使用%s或命名PARAMS。 – pvg

回答

2

回答所以其他人不会经历我必须进行的调试!

我在我们的代码中的其他查询中编写了查询建模,该代码使用了准备好的语句并使用'?'以指示参数。但你不能这样做 for executemany()!它必须使用'%s'。更改为以下内容:

cursor.executemany('INSERT INTO temp VALUES(%s,%s,%s)', batch) 

...导致百倍的速度提升,并且可以使用SHOW PROCESSLIST查看优化的单个查询。谨防标准'?'句法!

+0

在大多数情况下,您仍应使用预准备语句来避免SQL注入。为了便于批量插入,mysql中内置了许多其他机制。最值得注意的是LOAD DATA INFILE,这会比你执行很多 – e4c5

+0

@ e4c5的问题要快得多。我不确定海报的用途,但%s不是?是整个mysql连接器游标api的值占位符。 – pvg

+0

这正是我所说的。我现在知道%s是正确的占位符,但只是因为'?'没有被优化,不是因为它没有工作。 ?工作得很好。这就是调试的巨大痛苦。 – blueimpb