如何使用SQL OUTER JOIN高效地加入巨型表

时间:2013-03-18 16:55:40

标签: sql performance oracle join oracle10g

Oracle 10g 64位 红帽企业Linux 5 64位

我目前可以访问规范化的第三方数据库。它们拥有大量数据,我的要求是通过连接大量表来公开物化VIEW。

表1:Example_Master 列:MasterID(VARCHAR2(250))MasterName(VARCHAR2(250)) 行数:9000万 主键:MasterID

表2:Example_ChildA1 列:ChildA1ID(VARCHAR2(250))MasterID(VARCHAR2(250)) 行数:2500万

表3:Example_ChildA1ID 列:ChildA1ID(VARCHAR2(250))ChildA1Name(VARCHAR2(250)) 主键:ChildA1ID

表4:Example_ChildA2 列:ChildA2ID(VARCHAR2(250))MasterID(VARCHAR2(250)) 行数:3500万

表5:Example_ChildA2ID 列:ChildA2ID(VARCHAR2(250))ChildA2Name(VARCHAR2(250)) 主键:ChildA2ID

等,

每个子表可能有也可能没有等同于MASTERID的条目。所以我必须获得所有MASTERID及其相关的CHILD名称。如果没有任何Child的等效值,那么它必须返回'NULL'。所以我现在已经在Materialized VIEW语法下面了

 SELECT a.MasterName, c.ChildA1Name, e.ChildA2Name, g.ChildA3Name
 FROM 
 Example_Master a,
 Example_ChildA1 b,
 Example_ChildA1ID c,
 Example_ChildA2 d,
 Example_ChildA2ID e,
 Example_ChildA3 f,
 Example_ChildA3ID g
 WHERE 
 c.ChildA1ID(+) = b.ChildA1ID
 AND e.ChildA2ID(+) = d.ChildA2ID
 AND g.ChildA3ID(+) = f.ChildA3ID
 AND a.MasterID=b.MasterID (+)
 AND a.MasterID=d.MasterID (+)
 AND a.MasterID=f.MasterID (+)

我必须加入另外5个像上面这样的子表,并且这个查询的成本已经变得如此巨大,以至于需要将近16分钟来获得结果。有没有更好的方法来使用OUTER JOINS?如果您需要有关我的问题的更多详细信息,请告诉我。

谢谢!

1 个答案:

答案 0 :(得分:5)

当您平等加入这样的大表时,您可以希望的最佳计划是一组散列外连接,其成本通常等于全表扫描的成本加上溢出的大型散列表的开销磁盘。

如果有覆盖索引,则只能真正降低全表扫描的成本。

散列表溢出到磁盘的可能性当然可以通过提供大量可用内存来减少,但也可以通过对连接键上的表进行等分来帮助。通常,这是通过散列分区完成的,使用尽可能多的散列分区来防止将哈希表保留在内存中。更多来自文档:https://docs.oracle.com/cd/B28359_01/server.111/b32024/part_avail.htm#CIHCDBIF(或搜索“分区智能连接”)

请注意,您不需要使用并行查询来从分区连接中受益 - 串行查询也会带来好处。

顺便说一句,不要感谢你没有使用低于10g的版本 - 你无法有效地与LARGE_TABLE LEFT OUTER JOIN SMALL TABLE等同连接,因为优化器无法首先访问小型表来创建哈希表 - 这将始终是一个嵌套循环:(