【问题标题】:Performing join on two big tables在两个大表上执行连接
【发布时间】:2018-12-22 22:43:14
【问题描述】:

我正在尝试加入两个大表;让我们称它们为tableA(1.5 亿行)和tableB(1.4 亿行)。以下查询返回 490 行,执行大约需要 20-25 秒(这是不可接受的)。

select distinct
    a.key_fk
from tableA a 
join tableB b on a.key_fk = b.key_fk 
where customFunc(b.valueX) = 'xyz' 
and customFunc(a.valueY) = 'abc';
  • a.key_fkb.key_fk 是引用另一个表 c 的外键(但这不相关)
  • 两个表都有key_fk上的索引
  • tableAcustomFunc(valueY) 上有一个索引,tableBcustomFunc(valueX) 上有一个索引
  • select count(key_fk) from tableA where customFunc(valueY)='abc' 大约需要 7-8 秒,返回 500 万行
  • select count(key_fk) from tableB where customFunc(valueX)='xyz' 大约需要 0.5 秒并返回 80k 行

我还能做些什么来提高上述查询的性能吗?

【问题讨论】:

  • 执行计划是什么?
  • 发布执行计划。请参阅here 一些提示如何获取它。

标签: database oracle performance join


【解决方案1】:

创建包含查询所需的所有列的索引可能会提高速度,因为它可以完全避免读取实际的表行。您可能需要对索引中的列顺序进行试验,以查看最有效的方法(或者它可能根本没有帮助)。

根据您的描述,我怀疑查询首先使用函数索引访问 tableB 中的行,然后根据连接列查找 tableA 中的行,然后按最后一个条件过滤。这只是一个猜测,看看实际的执行计划会很有帮助。

如果这个猜测是正确的,在tableA ( key_fk, customFunc(valueY) ) 上创建一个索引应该可以让它进行更精确的索引查找并完全避免从 tableA 读取行。

【讨论】:

    【解决方案2】:

    我会重写查询(不需要加入所有记录):

    select key_fk
    from   tableA a 
    where  customFunc(valueY) = 'abc'
    intersect
    select key_fk
    from   tableB
    where  customFunc(valueX) = 'xyz'
    

    加快速度的另一点是遵循 Dave Costa 的建议 - 创建包含所有必需列的索引。我会创建tableA(customFunc(valueY), key_fk)tableB(customFunc(valueX), key_fk)

    希望对您有所帮助。

    【讨论】:

      【解决方案3】:

      根据函数值和FK 定义两个表的索引(假设函数是确定性的)。

      create index idxA on tableA (customFunc(valueX), key_fk);
      create index idxB on tableB (customFunc(valueY), key_fk);
      

      您将看到如下执行计划,仅访问索引范围扫描(无表访问)并执行哈希连接,这应该会导致可接受的性能:

      ----------------------------------------------------------------------------------------------------------------
      | Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
      ----------------------------------------------------------------------------------------------------------------
      |   0 | SELECT STATEMENT   |      |      1 |        |     50 |00:00:00.08 |    1484 |       |       |          |
      |   1 |  HASH UNIQUE       |      |      1 |    138K|     50 |00:00:00.08 |    1484 |    11M|  3061K|          |
      |*  2 |   HASH JOIN        |      |      1 |    140K|   3155 |00:00:00.01 |    1484 |  2168K|  2168K| 1958K (0)|
      |*  3 |    INDEX RANGE SCAN| IDXB |      1 |    140K|   8489 |00:00:00.01 |      27 |       |       |          |
      |*  4 |    INDEX RANGE SCAN| IDXA |      1 |    150K|    500K|00:00:00.07 |    1457 |       |       |          |
      ----------------------------------------------------------------------------------------------------------------
      
      Predicate Information (identified by operation id):
      ---------------------------------------------------
      
         2 - access("A"."KEY_FK"="B"."KEY_FK")
         3 - access("B"."SYS_NC00003$"='xyz')
         4 - access("A"."SYS_NC00003$"='abc')
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-08-23
        • 1970-01-01
        • 2013-08-19
        • 2020-10-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多