我正试图加入两个大表;让我们称它们为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-8s,并返回500万行select count(key_fk) from tableB where customFunc(valueX)='xyz'
大约需要0.5秒并返回8万行还有什么我可以做的,以提高提到的查询的性能?
答案 0 :(得分:0)
可能地,创建包含查询所需的所有列的索引将提高速度,因为它可以完全避免读取实际的表行。您可能需要对索引中的列顺序进行试验,以查看哪种方法最有效(或者可能根本无济于事)。
根据您的描述,我怀疑查询首先是使用函数索引访问tableB中的行,然后根据join列在tableA中查找行,然后按最后一个条件进行过滤。这只是一个猜测,有助于查看实际的执行计划。
如果这种猜测是正确的,那么在tableA ( key_fk, customFunc(valueY) )
上创建索引应该可以使其进行更精确的索引查找,并且完全避免从tableA中读取行。
答案 1 :(得分:0)
我将重写查询(无需连接所有记录):
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)
希望有帮助。
答案 2 :(得分:0)
基于函数值和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')