1

我们有很多使用可以为 Null 的绑定变量的选择语句。Null 表示 Bind-Value 不应限制语句。

这是我们正在做的一个简单示例:

CREATE TABLE PERSON AS
SELECT LEVEL AS ID, 'Person_'||LEVEL AS NAME
FROM DUAL 
CONNECT BY LEVEL <= 5000;

create index IPERSON1 on PERSON(NAME, ID);

begin
dbms_stats.gather_table_stats(user, 'PERSON');
end;

select * from PERSON
where NAME = nvl(:b1, NAME);

select * from PERSON
where (NAME =:b1 or :b1 is null);

这 2 个语句具有以下执行计划:

select * from PERSON where NAME =nvl(:b1, NAME): 
------------------------------------------------------------------------------------
| Id  | Operation              | Name     | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |          |        |       |     4 (100)|          |
|   1 |  CONCATENATION         |          |        |       |            |          |
|*  2 |   FILTER               |          |        |       |            |          |
|*  3 |    INDEX FAST FULL SCAN| IPERSON1 |    500 |  7500 |     2   (0)| 00:00:01 |
|*  4 |   FILTER               |          |        |       |            |          |
|*  5 |    INDEX RANGE SCAN    | IPERSON1 |      1 |    15 |     2   (0)| 00:00:01 |
------------------------------------------------------------------------------------

select * from PERSON where (NAME =:b1 or :b1 is null): 
-----------------------------------------------------------------------------
| Id  | Operation         | Name   | E-Rows |E-Bytes| Cost (%CPU)| E-Time   |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |        |        |       |     3 (100)|          |
|*  1 |  TABLE ACCESS FULL| PERSON |     26 |   390 |     3   (0)| 00:00:01 |
-----------------------------------------------------------------------------

那么,您认为这种外连接的最佳解决方案是什么?

4

1 回答 1

2

我认为这个问题一般不能回答,因为它取决于特定的表模式和可用索引。

一般可以说的是:

  • 两个提议的 WHERE 条件都无法通过索引查找直接找到相关行。相反,必须完全扫描表或索引。

  • 将同一查询的不同变体合并为一个被认为是一种反模式,因为 Oracle 必须对所有变体使用相同的执行计划,这很可能对所有变体都不是最佳的。

所以这可能会更好:

  1. 动态构建查询,即仅当参数不为空时才添加 WHERE 条件。如果存在 WHERE 条件,那么您仍应使用绑定参数,这对于优化性能至关重要。

  2. 或者,根据参数是否为空来实现单独的查询。

选项 1 是首选选项。如果您运行 C#、Java 或类似语言的查询,它可能更容易实现。

选项 2 是您可能会在 PL/SQL 中使用的选项。但是,如果您有多个可以为空的参数,它可能会导致许多不同的查询。

于 2012-12-03T15:12:58.970 回答