PostgreSQL:更新3m记录的有效方法是什么?

时间:2009-08-19 17:36:18

标签: sql postgresql

我的工作中的一个dumbveloper(多年前)将body列从我们的comments表移动到辅助comment_extensions表,作为某种粗略的猜测优化。每次我们想要显示注释时进行连接似乎都是不明智的,所以我将尝试将该列移回我们的comments表并运行一些基准测试。

我的问题是此更新抓取了。我让它运行了一个小时才把它关掉,担心它需要整晚。

UPDATE comments SET body = comment_extensions.body 
                FROM comment_extensions 
                WHERE comments.id = comment_extensions.comment_id;

这是一个PostgreSQL 8.1数据库,comment_extensions.comment_id被编入索引。

有什么建议可以让它更快地运行?

3 个答案:

答案 0 :(得分:2)

那么,对于一个学术问题,为什么这是不明智的?查找的百分比涉及需要知道评论信息?

我的建议:小批量更新(一次10,000行?)。它可能仍然需要整晚。根据系统的性质,您可能还必须实施切换逻辑,以防止系统在迁移期间更新或从扩展表中提取。

大型数据库像这样受伤;)

答案 1 :(得分:2)

这个怎么样?

http://www.postgresql.org/docs/8.1/interactive/sql-createtableas.html

CREATE TABLE joined_comments
    AS SELECT c.id, c.author, c.blablabla, ce.body
    FROM comments c LEFT JOIN comment_extensions ce
    ON c.id = ce.comment_id;

这将创建一个新的joined_comments表。这可能已经足够了(你还需要重新创建索引等)但我记得Postgres 8.1有一个关于串行列创建方式的错误(抱歉无法找到链接)。

所以我的建议是,在你有了这个新的连接表之后,然后你从join_comments表中复制到一个BINARY文件,创建一个新的注释表,说明id从一开始就是一个SERIAL,然后从那个BINARY复制将文件发送到新的评论表。然后,重新创建索引。

答案 2 :(得分:1)

执行此操作时,您可能会从禁用日志中获得一些好处。如果它是非生产表中的测试,您可能不需要日志文件提供的保护。

如果comments.body上有索引或键,则在更新之前删除它,然后重新创建它。

comments.body字段是固定宽度的char(N)还是varchar? Varchar曾经比char()慢,我怀疑它仍然是。所以使用char not varchar。

如果你选择将数据合并到数据文件(例如,引用csv)并编写脚本将其转换为INSERTS,那么清空注释表并使用可能比查询更快的INSERTS加载它虽然comments.id上的索引有助于提高速度。

3e6记录无论如何都需要一段时间。