【问题标题】: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_fk 和 b.key_fk 是引用另一个表 c 的外键(但这不相关)
- 两个表都有
key_fk上的索引
-
tableA 在customFunc(valueY) 上有一个索引,tableB 在customFunc(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')