我有一个很大的合同表,我们有很多存储过程来查询状态为Open的合同。不到10%的合同是开放的,随着数据库的增长,这个数字正在缩小。我想我可以创建一个开放合同的索引视图,以加快我们的一些查询。问题是状态不在合同表上,我需要一个子查询来检索我想要的数据。 (SQL Server然后在我查看的查询中对整个表执行聚簇索引扫描)
以下是视图的精简版本(我从合约表中删除了其他30个列)
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE VIEW [dbo].[vw_OpenContractsIndexed]
WITH SCHEMABINDING
AS
SELECT c.ContractID
FROM dbo.NMPT_Contract AS c INNER JOIN
dbo.NMPT_ContractStatus AS cs ON c.ContractID = cs.ContractID AND cs.ContractStatusCreated =
(SELECT MAX(ContractStatusCreated) AS Expr1
FROM dbo.NMPT_ContractStatus AS cs2
WHERE (ContractID = c.ContractID)) INNER JOIN
dbo.CMSS_Status AS s ON cs.StatusID = s.StatusID
WHERE (s.StatusCode = 'OPN')
如果我尝试在视图上创建索引(contractid
上的唯一群集),我会得到以下内容
索引的创建失败 它包含一个或多个不允许的构造。 (Microsoft SQL Server,错误1936)
从我可以收集到的是子查询中的Max是问题吗?
除了将状态放在合同表(我个人认为它属于)之外,是否有任何优化这种情况的建议。如果不这样,其他版本的SQL Server会允许这个索引视图吗?
答案 0 :(得分:3)
From TechNet regarding Indexed Views in SS 2000:
视图定义的语法有几个限制。 视图定义不得包含以下内容:
COUNT(*)
ROWSET功能
派生表
自连接
DISTINCT
STDEV,VARIANCE,AVG
Float *,text,ntext,image columns
子查询
全文谓词(CONTAIN,FREETEXT)
关于可空表达式的SUM
MIN,MAX
TOP
OUTER join
UNION
您正在使用MAX
和子查询,这两个都是不允许的。
要获得有关如何解决这个问题的建议,您需要分享一些数据以及您要做的事情。
答案 1 :(得分:1)
它不是“视图”解决方案,需要完成更多工作,但您可以创建非规范化表,该表将保存视图的结果。这样,Open合同的所有读取都可以违反该表。这将是最快的,但需要维护新表。
答案 2 :(得分:0)
创建一个索引视图是一个安静的difficuylt任务,因为它有很多restirction,一个也与self join相关。你有自己加入这里。没有其他意见等。
对于这些主表的其他事情,如果你只使用像'OPEN'这样的单一状态,我建议不要加入表(带有状态代码的主表)而只是声明statusid变量然后存储状态OPEN的值,然后在最终查询中使用该值。这将避免与主表的额外连接。
我建议您在最终语句中加入合同表之前将临时表中的打开状态数据存储起来。您可以在statusid,customerid和contractcreationdate上建立索引。然后强制使用此索引将contractId转换为临时表,如
select contractid into #temp from NMPT_ContractStatus
where statusid =@statusid group by contractid
having datefield = max(datefield)
现在将此临时表与Contract表连接。
但在创建任何类型的索引之前,请确保这些索引的开销远低于您获得的收益。