【发布时间】:2019-01-12 14:25:45
【问题描述】:
假设我们有一个 EMPLOYEE 表,我们要使用以下字段(我们在其上建立索引)上的三个过滤器进行查询:subsidy_id、employee_id、last_name。
如果我们在where子句中使用简单的过滤器和参数绑定的动态SQL构造查询,例如:WHERE last_name = :name,则使用索引并且响应快。
现在的问题是,如果我们在查询中使用 SMART Logic 来用静态 SQL 构造查询,这样:
SELECT subsidiary_id, employee_id, last_name
FROM EMPLOYEE
WHERE (:sub_id IS NULL OR subsidiary_id = :sub_id)
AND (:emp_id IS NULL OR employee_id = :emp_id)
AND (:name IS NULL OR last_name = :name)
即使执行了查询,并且由于所有可能的过滤器表达式都在语句中静态编码,因此避免了使用动态 SQL 的需要,但由于数据库(Oracle)无法优化执行计划,因此会导致反模式对于一个特定的过滤器(因为它们中的任何一个都可以在运行时被取消),它必须为最坏的情况(所有过滤器被禁用)执行全表扫描做准备,即使每列都有一个索引用于过滤器。
问题是:如果将带有智能逻辑的查询放在存储过程/函数中会发生什么? 数据库是否足够智能以使用索引或执行全表扫描,如使用绑定参数提交的查询?
Oracle 存储过程正文:
create procedure myproc (employee_id IN NUMBER, subsidiary_id IN NUMBER, name IN VARCHAR2, prc out sys_refcursor)
is
begin
open prc for (SELECT e.subsidiary_id, e.employee_id, e.last_name
FROM EMPLOYEE e
WHERE (subsidiary_id IS NULL OR e.subsidiary_id = subsidiary_id)
AND (employee_id IS NULL OR e.employee_id = employee_id)
AND (name IS NULL OR e.last_name = name)
);
end;
如果在存储过程或函数中执行,查询是否使用索引?
【问题讨论】:
-
相同的查询使用相同的解释计划,无论是从存储过程调用还是在 SQL*Plus(或其他)中运行。
-
运行你的程序并使用来自该线程的提示检查解释计划:asktom.oracle.com/pls/apex/…,你会看到。