【问题标题】:How can I speed up a diff between tables?如何加快表之间的差异?
【发布时间】:2011-09-14 08:05:50
【问题描述】:

我正在研究 postgresql 中的表之间的差异,这需要很长时间,因为每个表约为 13GB... 我目前的查询是:

SELECT * FROM tableA EXCEPT SELECT * FROM tableB;

SELECT * FROM tableB EXCEPT SELECT * FROM tableA;

当我对两个(未索引的)表进行比较时,需要 1:40 小时(1 小时 40 分钟)为了获得新行和已删除行,我需要运行两次查询,从而获得总时间到 3:30。

我对它运行了 Postgresql EXPLAIN 查询以查看它在做什么。看起来它正在对第一个表进行排序,然后是第二个表,然后比较它们。好吧,这让我想到,如果我对表进行索引,它们将被预先排序,并且差异查询会更快。

索引每个表需要 45 分钟。索引后,每个 Diff 需要 1:35 小时。 为什么索引只将总差异时间缩短 5 分钟?我会假设它会超过一半,因为在未索引的查询中,我对每个表进行了两次排序(我需要运行两次查询)

由于其中一个表不会有太大变化,因此只需索引一次,另一个将每天更新。所以索引方法的总运行时间是索引的 45 分钟,加上 diff 的 2x 1:35,总共 3:55 小时,差不多 4 小时。

我在这里做错了什么,我看不出为什么我的净差异时间比没有它的索引大?

这里稍微引用了我的另一个问题:Postgresql UNION takes 10 times as long as running the individual queries

编辑: 这是两个表的架构,除了表名之外它们是相同的。

CREATE TABLE bulk.blue
(
  "partA" text NOT NULL,
  "type" text NOT NULL,
  "partB" text NOT NULL
)
WITH (
  OIDS=FALSE
);

【问题讨论】:

  • 报告explain analyze 将非常有帮助,并且在您进行更改后进行比较分析时应该始终这样做。例如,它会表明您在添加索引后仍然没有使用它们。顺便说一句,一旦您使用了正确的查询,对索引进行聚类会使其工作得更快。

标签: performance postgresql indexing diff


【解决方案1】:

在上面的语句中,您没有使用索引。

你可以这样做:

SELECT * FROM tableA a
  FULL OUTER JOIN tableB b ON a.someID = b.someID

然后您可以使用相同的语句来显示哪些表有缺失值

SELECT * FROM tableA a
  FULL OUTER JOIN tableB b ON a.someID = b.someID
  WHERE ISNULL(a.someID) OR ISNULL(b.someID)

这应该为您提供表 A 或表 B 中缺少的行

【讨论】:

  • someID 可以是任何字段,但它应该被索引。
  • 我正在尝试使用您的示例,但连接中有两个条件(我有 3 列,两个组合是唯一的,第三个不是。
  • 这里是实际查询和错误:SELECT * From bulk."redNet" r full external join bulk."blueNet" b on (r.partA=b.partA) and (r.partB= b.partB) 其中 ISNULL(r.type) 或 ISNULL(b.type);错误:列 r.parta 不存在
  • 我猜我犯了一个简单的错误,有什么想法吗?
  • 我发现了我的 1 个问题。 “类型”必须用引号引起来,并且没有 isnull() postgresql 函数,它必须是:(表达式 IS NULL)。它现在正在运行,我会计时,看看需要多长时间。
【解决方案2】:

确认您正在使用索引(它们可能不在这样的通用 except 语句中),但您没有针对指定的列进行连接,因此很可能缺少显式连接不会导致优化查询:

http://www.postgresql.org/docs/9.0/static/indexes-examine.html

这将帮助您更清楚地查看解释分析:

http://explain.depesz.com

另外,如果您希望它立即表现良好,请确保在创建索引后对表进行分析:}

【讨论】:

  • 感谢第二个链接,它很有帮助。
【解决方案3】:

指定的查询需要比较表的每一列。

例如,如果 tableA 和 tableB 各有五列,则查询必须将 tableA.col1 与 tableB.col1、tableA.col2 与 tableB.col2 进行比较。 . . tableA.col5 到 tableB.col5

如果只有少数列可以唯一标识一条记录,而不是表中的所有列,那么在唯一标识一条记录的特定列上加入表将提高您的性能。

上面的语句假设没有创建主键。如果已定义主键以指示哪些列唯一标识一条记录,那么我相信 EXCEPT 语句会考虑到这一点。

【讨论】:

    【解决方案4】:
    • 您应用了哪种索引?索引仅对改善WHERE 条件有用。如果您正在执行select *,则您正在获取所有字段并且索引可能没有做任何事情,而是占用空间,并在后台添加更多处理以供 db-engine 比较查询索引缓存。

    • 除了SELECT *,您可以尝试选择您的唯一字段并为这些唯一字段创建索引

    • 您还可以使用OUTER JOIN 来显示两个表中在唯一字段上不匹配的结果
    • 您可能需要考虑对表进行聚类
    • 您运行的是哪个版本的 Postgres?
    • 您上一次吸尘是什么时候?

    除上述之外,13GB 相当大,因此您需要检查您的配置设置。运行它应该不会花费数小时,除非您的系统上没有足够的内存。

    【讨论】:

    • 一共有三列,三列都有索引。如果所有列都被索引,您是说“Select *”不使用索引,而“Select col1, col2, col3”将使用索引?
    • 你肯定要查看查询计划,但是是的,这就是我要说的,但是 Postgres 是一个高级数据库,所以如果它在这些数据库上进行查找,我不会感到惊讶三列。将查询计划输出转储到pastebin.com 会更有帮助
    猜你喜欢
    • 2017-01-27
    • 2020-08-25
    • 2011-01-18
    • 2013-01-02
    • 2012-03-31
    • 2020-01-31
    • 2013-01-16
    • 2015-01-16
    • 1970-01-01
    相关资源
    最近更新 更多