具有空查询参数的Oracle FTS执行计划(pl/sql)

具有空查询参数的Oracle FTS执行计划(pl/sql),oracle,stored-procedures,sql-execution-plan,query-parameters,Oracle,Stored Procedures,Sql Execution Plan,Query Parameters,所以问题是,在存储过程中处理传入的空查询参数时,是否有可能避免完全扫描?假设我有4个参数,用户从表单发送并尝试在表中查找精确匹配,如下所示: SELECT * FROM table1 t1 WHERE ((:qParam1 is null) OR (t1.col1 = :qParam1)) AND ((:qParam2 is null) OR (t1.col2 = :qParam2)) AND ((:qParam3 is null) OR (t1.col3 = :qParam3)) AND ((

所以问题是,在存储过程中处理传入的空查询参数时,是否有可能避免完全扫描?假设我有4个参数,用户从表单发送并尝试在表中查找精确匹配,如下所示:

SELECT *
FROM table1 t1
WHERE ((:qParam1 is null) OR (t1.col1 = :qParam1)) AND
((:qParam2 is null) OR (t1.col2 = :qParam2)) AND
((:qParam3 is null) OR (t1.col3 = :qParam3)) AND
((:qParam4 is null) OR (t1.col4 = :qParam4));

因此,当程序的这一部分执行时,由于空检查,它将执行FTS,因为程序已经编译并且执行计划已经确定。需要在过程内部编写2^4个不同的查询,以便始终使用考虑传入查询参数的最有效的计划(如果输入参数数量增加,则会大大增加)。我的问题是-除了动态sql之外,还有什么方法可以避免此类查询中的FTS吗?

可能没有。Oracle不在索引中存储空值,因此当谓词中可能存在空值时,它永远无法使用索引。如果您的列可以为空,那么就不可以了。话虽如此,这很有可能是最好的计划——您的查询非常模糊(ok-flexible),因此很难构建一个有用的计划。甲骨文在灵活的计划方面相当聪明,但在这方面并没有太多进展

如果您确实有可为空的列和索引,那么您可能可以使用它进行编辑

t1.col1 = :qParam2 and t1.col1 is not null
如果它不够聪明,无法自己解决这个问题。

t1.col=nvl(:qParam1,t1.col)
通常可以正常工作。Oracle使用
FILTER
操作构建两个独立的子计划,一个带有FTS,一个带有索引,并将在运行时选择适当的计划。我会把这个标记为的副本,除非接受的答案是错误的。