我在以下示例代码中遇到了ORACLE的常见问题:
create or replace procedure usp_test
(
p_customerId number,
p_eventTypeId number,
p_out OUT SYS_REFCURSOR
)
as
begin
open p_out for
select e.Id from eventstable e
where
(p_customerId is null or e.CustomerId = p_customerId)
and
(p_eventTypeId is null or e.EventTypeId = p_eventTypeId)
order by Id asc;
end usp_test;
“(p_customerId为null或e.CustomerId = p_customerId)中的”OR“会导致程序性能下降,因为优化程序不会在”CustomerId“列上最佳地使用索引(我希望索引搜索),从而导致扫描而不是寻求。 “CustomerId”的索引有很多不同的值。
使用MSSQL 2008 R2(最新的SP)或MSSQL 2012时,我可以使用“选项(重新编译)”提示查询,这将:
例如:如果我传递p_customerId = 1000,那么“1000 is null”表达式将始终为false,因此优化器将忽略它。 这会增加一些CPU开销,但它主要用于很少被称为大规模报告的程序,所以这里没有问题。
在Oracle中有没有办法做到这一点? Dynamic-SQL不是一个选项。
相同的过程只是没有“p_customerId为空”而“p_eventTypeId为空”运行~0.041秒,而上层运行~0.448秒(我有~5000.000行)。
答案 0 :(得分:0)
一个列索引无法帮助,因为它没有存储在索引定义中。 是否允许创建索引(客户ID,事件ID,ID)?这样所有需要的列都在索引...
答案 1 :(得分:0)
CREATE INDEX IX_YOURNAME1 ON eventstable (NVL(p_customerId, 'x'));
CREATE INDEX IX_YOURNAME2 ON eventstable (NVL(p_eventTypeId, 'x'));
create or replace procedure usp_test
(
p_customerId number,
p_eventTypeId number,
p_out OUT SYS_REFCURSOR
)
as
begin
open p_out for
select e.Id from eventstable e
where
(NVL(p_customerId, 'x') = e.CustomerId OR NVL(p_customerId, 'x') = 'x')
AND (NVL(p_eventTypeId, 'x') = e.EventTypeId OR NVL(p_eventTypeId, 'x') = 'x')
order by Id asc;
end usp_test;