我正在尝试使用WHERE
子句执行查询(在Oracle SQL中),如下所示:
SELECT booking_line_id
FROM booking_line
WHERE (booking_line_id in
(SELECT sbli.booking_line_id
FROM search_booking_line_index sbli,
policy_record pr,
policy_record_revision prr
WHERE sbli.attribute_name = 2209
AND sbli.policy_record_id = pr.policy_record_id
AND pr.latest_revision_id = prr.policy_record_revision_id
AND LOWER(prr.broker_reference) LIKE '%123%'));
执行计划:
| 0 | SELECT STATEMENT | | 19027 | 334K| 455 (3)| 00:00:03 |
| 1 | NESTED LOOPS | | 19027 | 334K| 455 (3)| 00:00:03 |
| 2 | VIEW | VW_NSO_1 | 19027 | 241K| 449 (2)| 00:00:03 |
| 3 | HASH UNIQUE | | 19027 | 798K| | |
|* 4 | HASH JOIN | | 19027 | 798K| 449 (2)| 00:00:03 |
|* 5 | HASH JOIN | | 464 | 13456 | 31 (4)| 00:00:01 |
|* 6 | TABLE ACCESS FULL| POLICY_RECORD_REVISION | 464 | 9280 | 21 (0)| 00:00:01 |
|* 7 | TABLE ACCESS FULL| POLICY_RECORD | 4067 | 36603 | 9 (0)| 00:00:01 |
|* 8 | INDEX RANGE SCAN | SBLI_ATTRIBUTE_CDX | 166K| 2282K| 416 (1)| 00:00:03 |
|* 9 | INDEX UNIQUE SCAN | BOOKING_LINE_PK | 1 | 5 | 1 (0)| 00:00:01 |
此查询执行速度非常快,并且可以立即返回行。但是如果我添加OR
条件如下,则查询会挂起(或者需要很长时间):
SELECT booking_line_id
FROM booking_line
WHERE 1=0 or (booking_line_id in
(SELECT sbli.booking_line_id
FROM search_booking_line_index sbli,
policy_record pr,
policy_record_revision prr
WHERE sbli.attribute_name = 2209
AND sbli.policy_record_id = pr.policy_record_id
AND pr.latest_revision_id = prr.policy_record_revision_id
AND LOWER(prr.broker_reference) LIKE '%123%'));
执行计划:
| 0 | SELECT STATEMENT | | 166K| 811K| 484 (2)| 00:00:03 |
|* 1 | FILTER | | | | | |
| 2 | INDEX FAST FULL SCAN | BOOKING_LINE_PK | 166K| 811K| 66 (5)| 00:00:01 |
| 3 | NESTED LOOPS | | 1 | 43 | 419 (1)| 00:00:03 |
| 4 | NESTED LOOPS | | 1 | 23 | 418 (1)| 00:00:03 |
|* 5 | INDEX RANGE SCAN | SBLI_ATTRIBUTE_CDX | 1 | 14 | 417 (1)| 00:00:03 |
|* 6 | TABLE ACCESS BY INDEX ROWID| POLICY_RECORD | 1 | 9 | 1 (0)| 00:00:01 |
|* 7 | INDEX UNIQUE SCAN | POLICY_RECORD_PK | 1 | | 1 (0)| 00:00:01 |
|* 8 | TABLE ACCESS BY INDEX ROWID | POLICY_RECORD_REVISION | 1 | 20 | 1 (0)| 00:00:01 |
|* 9 | INDEX UNIQUE SCAN | POLICY_RECORD_REVISION_PK | 1 | | 1 (0)| 00:00:01 |
预计这应该与第一个查询相同。但令人惊讶的是,它没有。
任何人都可以帮我解释同样的原因吗?
答案 0 :(得分:2)
至少在11gR2中,计划和执行完全相同。这是我的设置:
CREATE TABLE table1 AS SELECT * FROM dba_objects WHERE object_id IS NOT NULL;
CREATE TABLE table2 AS SELECT * FROM dba_objects WHERE object_id IS NOT NULL
AND object_type = 'VIEW';
ALTER TABLE table1 ADD CONSTRAINT table1_pk PRIMARY KEY (object_id);
ALTER TABLE table2 ADD CONSTRAINT table2_pk PRIMARY KEY (object_id);
第一个查询的执行计划:
SQL> EXPLAIN PLAN FOR SELECT * FROM TABLE1
2 WHERE OBJECT_ID IN (SELECT OBJECT_ID FROM TABLE2);
SQL> SELECT * FROM TABLE(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2776518249
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 31523 | 6772K| 584 (1)|
| 1 | MERGE JOIN | | 31523 | 6772K| 584 (1)|
| 2 | TABLE ACCESS BY INDEX ROWID| TABLE1 | 396K| 78M| 575 (1)|
| 3 | INDEX FULL SCAN | TABLE1_PK | 396K| | 77 (0)|
|* 4 | SORT JOIN | | 31523 | 400K| 10 (30)|
| 5 | INDEX FULL SCAN | TABLE2_PK | 31523 | 400K| 7 (0)|
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("OBJECT_ID"="OBJECT_ID")
filter("OBJECT_ID"="OBJECT_ID")
SQL>
和第二个查询:
SQL> EXPLAIN PLAN FOR SELECT * FROM TABLE1
2 WHERE 1 = 0 OR OBJECT_ID IN (SELECT OBJECT_ID FROM TABLE2);
SQL> SELECT * FROM TABLE(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2776518249
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 31523 | 6772K| 584 (1)|
| 1 | MERGE JOIN | | 31523 | 6772K| 584 (1)|
| 2 | TABLE ACCESS BY INDEX ROWID| TABLE1 | 396K| 78M| 575 (1)|
| 3 | INDEX FULL SCAN | TABLE1_PK | 396K| | 77 (0)|
|* 4 | SORT JOIN | | 31523 | 400K| 10 (30)|
| 5 | INDEX FULL SCAN | TABLE2_PK | 31523 | 400K| 7 (0)|
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("OBJECT_ID"="OBJECT_ID")
filter("OBJECT_ID"="OBJECT_ID")
答案 1 :(得分:0)
似乎因为你让服务器改变了执行计划。 第一个查询是使用内连接执行的,这就是为什么它如此之快。 但是在第二个过程中,必须检查第一个条件,然后根据需要进行选择。您可以像这样更改查询:
select ...
from t
left join t2
where 1=0 or t2.id is not null