【问题标题】:How to efficiently JOIN HUGE tables using SQL OUTER JOIN如何使用 SQL OUTER JOIN 有效地 JOIN HUGE 表
【发布时间】:2013-03-07 02:54:37
【问题描述】:

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

我目前可以访问规范化的第三方数据库。这些有大量数据,我的要求是通过加入大量表来公开物化视图。

表 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”。所以我现在有下面的物化视图语法

 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?如果您需要有关我的问题的更多详细信息,请告诉我。

谢谢!

【问题讨论】:

  • 加入VARCHAR。这应该很有趣。
  • 对不起。错误的列类型。 ID 都是数字。 Table 1: Example_Master Columns: MasterID (NUMBER) MasterName (VARCHAR2(250)) Rows: 90 Million Primary Key: MasterID Table 2: Example_ChildA1 Columns: ChildA1ID (NUMBER) MasterID(NUMBER) Rows: 25 Million Table 3: Example_ChildA1ID Columns: ChildA1ID (NUMBER) ChildA1Name(VARCHAR2(250)) Primary Key: ChildA1ID Table 4: Example_ChildA2 Columns: ChildA2ID (NUMBER) MasterID(NUMBER) Rows: 35 Million Table 5: Example_ChildA2ID Columns: ChildA2ID (NUMBER) ChildA2Name(VARCHAR2(250)) Primary Key: ChildA2ID
  • 首先从放弃隐式语法开始。使用它是一种 SDQL 反模式。然而,就个人而言,地球上没有办法让它更快。您返回的行数可能超过 1 亿行。在需要时进行带有 where 子句的单个查询会比这个庞大的视图更好。
  • 无需进一步说明,您似乎在此处的 WHERE 部分有问题: b.ChildA1ID(+)=c.ChildA1ID 将“c”表保留为强制性且没有附加条件。它看起来像错误。
  • 您可以编辑自己的问题。请这样做以更正您发布的错误,而不是添加 cmets。如果您的问题完整且易于阅读,您更有可能快速获得解决方案。

标签: sql performance oracle join oracle10g


【解决方案1】:

当您像这样对大型表进行 equi-join 时,您可以期望的最佳计划是一组散列外部联接,其成本通常等于全表扫描的成本加上大型散列表溢出到磁盘。

只有存在覆盖索引,才能真正降低全表扫描的成本。

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

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

顺便说一句,感谢您使用的不是低于 10g 的版本——您无法有效地与 LARGE_TABLE LEFT OUTER JOIN SMALL TABLE 进行等值连接,因为优化器无法首先访问小表来创建一个哈希表——这总是一个嵌套循环:(

【讨论】:

  • Oracle 文档的链接失效。
  • @Mouad_S 谢谢,已修复。
猜你喜欢
  • 2014-08-10
  • 1970-01-01
  • 2019-08-01
  • 2015-01-10
  • 1970-01-01
  • 2011-03-14
  • 2014-11-25
  • 2019-07-06
  • 2013-03-10
相关资源
最近更新 更多