2017-01-07 53 views
1

我需要运行以下类型的查询:Postgres的运行并行查询(大表上的交叉连接)

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的(AX,BY)利用指标上斧,通过 - 没有他们就显得更慢。

这将是一个合理的解决方案? 目前10k x 2M查询使用50处理器与天真拆分建议下面花了大约20分钟。

我正在考虑运行交叉连接上并行B的部分。 B将通过(整数主键)

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

和运行多个 “的psql -d MYDATABASE subqueryNumberX.sql” 使用GNU并行命令ID的值进行分割。

一些问题:

  1. 如果我有一个索引表T和其他查询将在搜索中使用的T索引中使用选择呢?或者这个subSELECT破坏它?

  2. 在上述我的查询,将选择表中的一个部分的(WHERE A.id BETWEEN N和M)防止使用索引?

  3. 当(慢)交叉联接在桌子上正在进行这样表进行其他操作(下一个交叉连接)访问?

+1

'myfunction()'如何使用索引?它在幕后做了些什么。如果交叉连接中有300万行和100000行,则交叉连接会处理300亿行(3E11行)。在每行1000毫秒(又称1秒),每年3E7秒的情况下,假设你有1000个可用的CPU,你应该在大约10年后得到答案。当你得到100倍的数据时,你可能会得到关于下一个千年的开始的答案 - 除非系统必须在此期间进行升级或修复了安全补丁。你有问题! –

+1

函数'myfunction'必须被调用100k * 10M = 1,000,000,000,000次才能执行连接。假设1次调用仅需1毫秒,则需要1,000,000,000秒(11,574天)才能在1个CPU上处理此加入。如果您购买11574处理器,那么查询需要1天(24小时) - 仍然假设1次函数调用仅需1毫秒。但是如果它需要200毫秒而不是1毫秒....你可以自己做这些计算。 – krokodilko

+0

在计算函数所需的时间估计中必定存在错误。看来postgres还记得以前几轮的计算结果。 10k x 2M查询使用50处理器与天真分裂建议在我的问题上面花了大约20分钟。如果我更了解sql,可能会改进它(请参阅上面的问题)。 –

回答

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(多版本并发控制)机制。