与SQLServer类似,我可以执行以下操作
create index TimeSeriesPeriodSs1 on TimeSeriesPeriod (validationStatus, completionStatus)
where completionStatus= N'Complete'
and validationStatus= N'Pending'
答案 0 :(得分:14)
您可以在Oracle中创建基于函数的索引,利用NULL值未存储在b-tree索引中的事实。像
这样的东西CREATE INDEX TimeSeriesPeriodSs1
ON TimeSeriesPeriod(
(CASE WHEN completionStatus = 'Complete' AND validationStatus = 'Pending'
THEN validationStatus
ELSE NULL
END),
(CASE WHEN completionStatus = 'Complete' AND validationStatus = 'Pending'
THEN completionStatus
ELSE NULL
END)
);
答案 1 :(得分:12)
您可能可以使用基于函数的索引,但这种情况不是很愉快:
create index TimeSeriesPeriodSs1 on TimeSeriesPeriod (
case when validationStatus= N'Pending' and completionStatus= N'Complete' then validationStatus else null end,
case when validationStatus= N'Pending' and completionStatus= N'Complete' then completionStatus else null end);
您必须使查询的where
子句完全匹配才能使其使用索引。
select <fields>
from TimeSeriesPeriod
where case when validationStatus= N'Pending' and completionStatus= N'Complete' then validationStatus else null end = N'Pending'
and case when validationStatus= N'Pending' and completionStatus= N'Complete' then completionStatus else null end = N'Complete';
如果您可以定义(确定性)函数来执行case
,那么这将更加整洁。有关更多信息和示例,请参阅here。或者来自快速Google的this。
答案 2 :(得分:6)
以下是Justin和Alex的答案的一个小变体,它可以节省更多索引空间并使修改后的查询更具可读性IMO:
CREATE INDEX TimeSeriesPeriodSs1
ON TimeSeriesPeriod(
(CASE WHEN completionStatus = 'Complete' AND validationStatus = 'Pending'
THEN 1
ELSE NULL
END);
SELECT * FROM TimeSeriesPeriod
WHERE 1 = (CASE WHEN completionStatus = 'Complete' AND validationStatus = 'Pending'
THEN 1
ELSE NULL
END)
答案 3 :(得分:1)
基于函数的索引的潜在替代/改进之处是利用虚拟列。
create table TimeSeriesPeriod (
--...
pendingValidation as (
case when completionStatus = N'Complete' and validationStatus= N'Pending'
then 1
else null
) virtual
);
create index TimeSeriesPeriodSs1 on TimeSeriesPeriod (pendingValidation);
select * from TimeSeriesPeriod where pendingValidation = 1;
请注意,就像常规列一样,为虚拟列/基于函数的索引收集统计信息,因此它们的成本确实为非零。考虑尽可能将多个过滤器折叠到一个虚拟列中
create table TimeSeriesPeriod (
--...
incompleteValidationStatus as (
case when completionStatus = N'Complete' and validationStatus != N'Complete'
then validationStatus
else null
) virtual
);
create index TimeSeriesPeriodSs1 on TimeSeriesPeriod (incompleteValidationStatus);
select * from TimeSeriesPeriod where incompleteValidationStatus = N'Pending';
select * from TimeSeriesPeriod where incompleteValidationStatus = N'Failed Validation';