在两个大表上执行联接

时间:2018-07-14 22:44:48

标签: database oracle performance join

我正试图加入两个大表;让我们称它们为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-8s,并返回500万行
  • select count(key_fk) from tableB where customFunc(valueX)='xyz'大约需要0.5秒并返回8万行

还有什么我可以做的,以提高提到的查询的性能?

3 个答案:

答案 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')