带订单的多个内部联接非常慢

时间:2011-11-10 23:42:56

标签: sql oracle join

我需要一些帮助来解决如何提高查询效率的方法。我不是SQL的专家,但我已经对此有所了解,但我正处于需要讨论/讨论的地步。

我有以下查询:

SELECT * FROM
(
SELECT
a.seq_num seq_num_a,
a.record_length record_length_a,
b.record_length record_length_b,
c.record_length record_length_c
a.deleted deleted_a,
b.deleted deleted_b,
c.deleted deleted_c
FROM tableA a
INNER JOIN tableB b
ON a.reference = b.reference
AND a.run_id = b.run_id
INNER JOIN tableC c
ON a.reference = c.reference
AND a.run_id = c.run_id
WHERE a.run_id = 1
)
WHERE deleted_a = 'N'
AND deleted_b = 'N'
AND deleted_c = 'N'
ORDER BY seq_num_a;

一旦我检查到deleted ='N',查询就会很慢 - 即使只是tableA。我将整个查询包装在SELECT中,认为子查询将返回数据集,然后它将是一个简单的检查和顺序。请注意,子查询中的检查没有性能差异。

在所有表中都存在针对run_id和删除的索引,并且针对tableA中的seq_num。每个表中大约有8000行。

查询计划

--------------------------------------------------------------------------------------
| Id  | Operation                      |  Name               | Rows  | Bytes | Cost  |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                     |     1 |   112 |     7 |
|   1 |  SORT ORDER BY                 |                     |     1 |   112 |     7 |
|   2 |   NESTED LOOPS                 |                     |     1 |   112 |     3 |
|   3 |    NESTED LOOPS                |                     |     1 |    79 |     2 |
|   4 |     TABLE ACCESS BY INDEX ROWID| TABLEC              |     1 |    33 |     2 |
|*  5 |      INDEX SKIP SCAN           | TABLEC_IDX2         |     1 |       |     2 |
|*  6 |     TABLE ACCESS BY INDEX ROWID| TABLEA              |     1 |    46 |       |
|*  7 |      INDEX RANGE SCAN          | TABLEA_IDX5         |     1 |       |       |
|*  8 |    TABLE ACCESS BY INDEX ROWID | TABLEB              |     1 |    33 |     1 |
|*  9 |     INDEX UNIQUE SCAN          | TABLEB_PK           |     1 |       |       |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   5 - access("C"."DELETED"='N')
       filter("C"."DELETED"='N')
   6 - filter("A"."REFERENCE"="C"."REFERENCE" AND 
              "A"."RUN_ID"="C"."RUN_ID")
   7 - access("A"."DELETED"='N')
   8 - filter("B"."DELETED"='N')
   9 - access("A"."RUN_ID"="B"."RUN_ID" AND 
              "A"."REFERENCE"="B"."REFERENCE")

Note: cpu costing is off

1 个答案:

答案 0 :(得分:0)

不确定外部选择提供什么值..根据oracle的版本,解释计划可能不同。但是在旧版本中,我发现在连接之前限制数据会大大提高性能。

因此从A开始并且获得最少量的记录以加入b然后到C比开始使用所有A,加入所有b并加入所有C然后通过where子句减少结果要快得多...但是后来查询优化器的版本考虑到了这一点,所以没有收获...那么......什么版本的oracle?

SELECT
a.seq_num seq_num_a,
a.record_length record_length_a,
b.record_length record_length_b,
c.record_length record_length_c
a.deleted deleted_a,
b.deleted deleted_b,
c.deleted deleted_c
FROM tableA a
INNER JOIN tableB b
  ON a.reference = b.reference
  AND a.run_id = b.run_id
  AND a.deleted = 'N'
  and b.deleted = 'N'
  and a.run_ID = 1
INNER JOIN tableC c
  ON a.reference = c.reference
  AND a.run_id = c.run_id
  and c.deleted = 'N'
ORDER BY seq_num_a;