在SQL语句中外连接绑定变量(Oracle 11g)

时间:2012-12-03 14:32:23

标签: sql oracle11g bind-variables

我们有很多选择语句,它们使用可以为空的Bind-Variables。 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 |
-----------------------------------------------------------------------------

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

1 个答案:

答案 0 :(得分:2)

我不认为这个问题一般可以回答,因为它取决于具体的表格模式和可用性索引。

通常可以说:

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

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

所以它可能会更好:

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

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

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

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