运行并行查询的Postgres(大型表上的交叉连接)

时间:2017-01-07 07:43:17

标签: sql postgresql join parallel-processing

我需要运行以下类型的查询:

SELECT * FROM A CROSS JOIN B WHERE myfunction(A.x,B.y) = Z

由于查询速度慢,我想使用所有可用的处理器加速查询。 我对关系数据库只有非常基本的知识,所以即使是“明显的”评论​​也是受欢迎的。

  • Postgres v 9.4.4(由于某些限制,升级不是一个选项)
  • A有3密耳行
  • B可以有100k行(但将来可能有10M行)
  • A,B有索引列
  • myfunction(A.x,B.y)利用A.x,B.y上的索引 - 没有它们甚至更慢。

什么是合理的解决方案? 目前,使用50个处理器进行10k x 2M查询,下面提出的天真拆分大约需要20分钟。

我正在考虑并行运行B部分的交叉连接。 B将被ID(整数主键)的值分割

SELECT * FROM A CROSS JOIN B WHERE myfunction(A.x,B.y) = Z  AND  A.id BETWEEN N and M.

使用gnu parallel运行多个“psql -d mydatabase subqueryNumberX.sql”命令。

有些问题:

  1. 如果我有一个索引表T并在另一个查询中使用SELECT,那么搜索中会使用T的索引吗?或者这个subSELECT摧毁它?

  2. 在我上面的查询中,选择表的一部分(WHERE A.ID BETWEEN N和M)是否会阻止使用索引?

  3. 当表上的(慢)交叉连接正在进行时,其他操作(下一次交叉连接)可以访问这样的表吗?

1 个答案:

答案 0 :(得分:0)

你的问题(仍然)相当含糊。

  1. 对于交叉连接,索引不一定有用,但它取决于索引的列以及查询中引用的列和表中行的大小。如果索引位于相关列上,那么优化器可能只会执行索引'扫描而不是全表扫描'并从较少量的I / O中受益。但是,由于您有SELECT *,因此您要从AB中选择所有列,因此需要读取整行(但请参阅第2点)。在查询中没有子选择,所以询问子选择是否会破坏任何东西都是不明智的。

  2. 名义上,您可以从将WHERE子句移动到子选项中获得一些好处,例如:

    SELECT *
      FROM (SELECT * FROM A WHERE A.id BETWEEN N AND M) AS A1
     CROSS JOIN B
     WHERE myFunction(A1.x, B.y) = Z
    

    然而,这将是一个微弱的优化器,不会自动执行此操作。范围条件可能使A.id上的索引具有吸引力,尤其是如果M和N代表A.id中值的总范围的一小部分。因此,优化器应使用带有A.id的索引作为前导或唯一组件,以允许它加速查询。条件不会阻止使用任何索引 - 索引几乎肯定不会被使用。

  3. 慢速查询不会禁止其他查询;它可能会在运行时禁止更新,或者它可能会强调DBMS的MVCC(多版本并发控制)机制。