好的我的巨人朋友再一次在我的肩膀上寻找一点空间:P
这是问题,我有一个python脚本正在修复一些数据库问题,但它花了太长时间,主要的更新声明是这样的:
cursor.execute("UPDATE jiveuser SET username = '%s' WHERE userid = %d" % (newName,userId))
使用不同的newName和userid对调用大约9500次......
有关如何加快流程的任何建议?也许某种程度上我可以通过一个查询来完成所有更新?
非常感谢任何帮助!
PS:Postgres是正在使用的数据库。
答案 0 :(得分:4)
将所有数据插入另一个空表(比如称为userchanges),然后在一个批处理中更新:
UPDATE jiveuser
SET username = userchanges.username
FROM userchanges
WHERE userchanges.userid = jiveuser.userid
AND userchanges.username <> jiveuser.username
请参阅the COPY command上的此文档,了解批量加载数据的信息。
还有tips for improving performance when populating a database。
答案 1 :(得分:3)
首先,不使用%运算符构造SQL。相反,将您的参数元组作为第二个参数传递给cursor.execute
,这也消除了引用您的参数并允许您将%s用于所有内容的需要:
cursor.execute("UPDATE jiveuser SET username = %s WHERE userid = %s", (newName, userId))
这对于阻止SQL Injection attacks很重要。
要回答您的问题,您可以通过在userid
列上创建索引来加速这些更新,这将允许数据库在O(1)
常量时间内更新,而不必扫描整个数据库表,O(n)
。由于您使用的是PostgreSQL,因此这里是创建索引的语法:
CREATE INDEX username_lookup ON jiveuser (userid);
编辑:由于您的评论显示您已在userid
列上有一个索引,因此您可能无法加快查询速度。因此,你的主要选择要么生活缓慢,要么这听起来像是一次性修复 - 破坏了事情,或者跟随VeeArr
的建议并测试cursor.executemany是否会给你足够的提升
答案 2 :(得分:3)
它花了这么长时间的原因可能是你已经启用了自动提交,每次更新都在自己的事务中完成。
这很慢,因为即使你有一个电池支持的raid控制器(你当然应该在所有数据库服务器上都有),它仍然需要为每个事务提交写入该设备以确保持久性。
解决方案是每个事务执行多行。但是不要让交易太大或者你也遇到问题。尝试将每10,000行更改作为一个粗略的猜测。
答案 3 :(得分:2)
您可能需要查看executemany()
:信息here
答案 4 :(得分:1)
也许你可以在userid上创建一个索引来加快速度。
答案 5 :(得分:1)
我会对此做一个解释。如果它正在进行索引查找以查找记录 - 如果你有一个userid索引它应该 - 那么我不知道你可以做些什么来提高性能。如果它没有使用索引,那么诀窍是找出原因并修复它。
哦,您可以尝试使用准备好的声明。使用9500插件,这应该有所帮助。
答案 6 :(得分:0)
将其移至存储过程并从数据库self执行。
答案 7 :(得分:0)
首先确保你有'userid'的索引,这将确保dbms不必每次都进行表扫描
CREATE INDEX jiveuser_userid ON jiveuser (userid);
接下来尝试准备语句,然后在其上调用execute。这将阻止优化器每次都检查查询
PREPARE update_username(string,integer) AS UPDATE jiveuser SET username = $1 WHERE userid = $2;
EXECUTE update_username("New Name", 123);
最后,通过关闭自动提交
可以挤出更多性能\set autocommit off