数据库查询优化

时间:2010-06-03 17:45:02

标签: python database postgresql query-optimization

好的我的巨人朋友再一次在我的肩膀上寻找一点空间:P

这是问题,我有一个python脚本正在修复一些数据库问题,但它花了太长时间,主要的更新声明是这样的:

cursor.execute("UPDATE jiveuser SET username = '%s' WHERE userid = %d" % (newName,userId))

使用不同的newName和userid对调用大约9500次......

有关如何加快流程的任何建议?也许某种程度上我可以通过一个查询来完成所有更新?

非常感谢任何帮助!

PS:Postgres是正在使用的数据库。

8 个答案:

答案 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
相关问题