我们有很多选择语句,它们使用可以为空的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 |
-----------------------------------------------------------------------------
那么,您认为这种外连接的最佳解决方案是什么?
答案 0 :(得分:2)
我不认为这个问题一般可以回答,因为它取决于具体的表格模式和可用性索引。
通常可以说:
两个提议的WHERE条件都无法通过索引查找直接找到相关的行。相反,必须完全扫描表格或索引。
将同一查询的不同变体合并为一种反模式被认为是一种反模式,因为Oracle必须对所有变体使用相同的执行计划,这很可能对所有变体都不是最理想的。
所以它可能会更好:
动态构建查询,即仅当参数不为null时才添加WHERE条件。如果存在WHERE条件,那么您仍然应该使用绑定参数,这对于获得最佳性能至关重要。
或者,根据参数是否为空来实现单独的查询。
选项1是首选选项。如果您运行C#,Java或类似语言的查询,则可能更容易实现。
选项2是您可能在PL / SQL中使用的选项。但是,如果您有多个可以为null的参数,则可能会导致许多不同的查询。