【问题标题】:efficienct SQL join for a range on large table大表范围内的高效 SQL 连接
【发布时间】:2013-03-26 05:23:00
【问题描述】:
    table1                            table2                   
    id      number                   start    end    indicator
    11      4                         1        5        N
    22      6                         2        7        N  
    33      8                         5        12       Y
    44      10

如果我想要其中的行,加入这些表的最有效方法是什么 table1 对应于 table2 (start,end) 的范围内,其中指标为 Y,用于两个单独的条件;

  1. table2 中只有一行会有 Y 指示符
  2. table2 中的一个或多个行将有一个 Y 指示符

即(坏例子)

SELECT * from table1
WHERE table1.number > (SELECT start from table2 WHERE indicator = 'Y')
AND   table1.number < (SELECT end from table2 WHERE indicator = 'Y')

【问题讨论】:

    标签: sql performance oracle memory-efficient


    【解决方案1】:
    select t1.* 
    from table1 t1, table2 t2
    where t2.indicator = 'Y'
    and t1.number1 > t2.start
    and t1.number1 < t2.end
    

    根据您的数据,您可能有兴趣使用并行查询http://docs.oracle.com/cd/E11882_01/server.112/e16638/optimops.htm#PFGRF94608

    【讨论】:

    • 万一有多个重叠范围并且您不想冒重复命中的风险,您可能需要使用DISTINCT t1.*
    • 在 table1 有数百万行并且经常被命中的情况下,由于这种连接方法创建了笛卡尔积,是否有更好的连接方法来提高性能(假设一个 Y 指标)?
    • @user2210179 如果您从中得到笛卡尔坐标,则优化器似乎做得非常糟糕(我怀疑Oracle不会这样做)。您始终可以将其重写为常规连接SELECT DISTINCT t1.* FROM table1 t1 JOIN table2 t2 ON t2.indicator = 'Y' AND t1."number" &gt; t2.start AND t1."number" &lt; t2.end;,但它提供了相同的计划。
    • 您的 table2 只有一行的 indicator='Y' (希望上面有索引),所以这里不是真正的笛卡尔积。 @Joachim 最后,这将只是一个大(或巨大)表扫描,将条件应用于来自 table2 的 1 行的每一行。
    【解决方案2】:
    从表 1 中选择 * 交叉连接 ( select start, end from table2 where indicator='Y') B 其中 table1.number > B.start 和 table1.number

    【讨论】:

      【解决方案3】:

      如果 table1 非常大,那么最有效的方法是将查询转换为等值连接,以便在数据集之间获得哈希连接。

      with table2_new as (
        select     start + rownum - 1 id
        from       table1
        where      indicator = 'Y'
        connect by level <= (end - start) +1)
      select
        table1.id,
        table1.number
      from
        table1,
        table2_new
      where
        table1.id = table2_new.id;
      

      没有测试过,但以前使用过这种技术。

      【讨论】:

        猜你喜欢
        • 2012-09-18
        • 1970-01-01
        • 2021-09-11
        • 2021-07-02
        • 2013-10-17
        • 1970-01-01
        • 2017-06-09
        • 2015-04-16
        • 1970-01-01
        相关资源
        最近更新 更多