索引视图和左连接一劳永逸

时间:2012-04-06 13:58:02

标签: sql sql-server sql-server-2008

我正在使用MSSQL Server 2008 R2,当我偶然发现索引视图时,我正在尝试优化我的视图。不幸的是,我的大多数视图都使用了索引视图不支持的左外连接。经过一系列的研究,我感到很困惑,最好的办法是解决这个问题。我看到它的方式,我有以下选择:

1)使用诀窍将左连接转换为内连接,以使用“OR(IsNull(a)AND IsNull(b))来模拟左连接”

我在几个地方找到了这个解决方案,但提到了性能损失。

2)将左连接转换为内连接,并用空guid(00000000-0000-0000-0000-000000000000)替换可空列的空值,并在右表中添加一行匹配guid。

这似乎是性能最明显的,但似乎每行都会浪费空间,否则会为NULL。

3)将我的视图分为两个视图。第一个视图是我的大部分逻辑,即Indexable。第二个视图派生自第一个视图并添加左连接。

这里的想法是,通过索引的基本视图可能会有性能提升。甚至查询派生的视图至少会获得一些性能上的好处。

4)不要将我的观点编入索引

是否会使视图保持比上述任何选项更高效的方式?

5)我没想到的想法

我将基本场景编写如下:

   CREATE TABLE [dbo].[tbl_Thumbnails](
        [ThumbnailId] [uniqueidentifier] NOT NULL,
        [Data] [image] NULL,
        [Width] [smallint] NOT NULL,
        [Height] [smallint] NOT NULL
     CONSTRAINT [PK_tbl_Thumbnails] PRIMARY KEY CLUSTERED 
    (
        [ThumbnailId] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

    GO

    CREATE TABLE [dbo].[tbl_Tags](
        [TagId] [uniqueidentifier] NOT NULL,
        [ThumbnailId] [uniqueidentifier] NULL
     CONSTRAINT [PK_tbl_Tags] PRIMARY KEY CLUSTERED 
    (
        [TagId] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]

    GO

    CREATE VIEW [dbo].[v_Tags] WITH SCHEMABINDING AS
    SELECT     dbo.tbl_Tags.TagId, dbo.tbl_Tags.ThumbnailId
    FROM         dbo.tbl_Tags LEFT OUTER JOIN
                          dbo.tbl_Thumbnails
    ON     dbo.tbl_Tags.ThumbnailId = dbo.tbl_Thumbnails.ThumbnailId

    GO

    INSERT INTO tbl_Tags VALUES ('16b23bb8-bf17-4784-b80a-220da1163584', NULL)
    INSERT INTO tbl_Tags VALUES ('e8b50f03-65a9-4d1e-b3b4-268f01645c4e', 'a45e357b-ca9c-449a-aa27-834614eb3f6e')
    INSERT INTO tbl_Thumbnails VALUES ('a45e357b-ca9c-449a-aa27-834614eb3f6e', NULL, 150, 150)

现在,执行以下查询会产生“无法在视图上创建索引”Test.dbo.v_Tags“因为它使用LEFT,RIGHT或FULL OUTER连接,并且在索引视图中不允许OUTER连接。请考虑使用INNER加入吧。“:

CREATE UNIQUE CLUSTERED INDEX [TagId] ON [dbo].[v_Tags] 
(
[TagId] ASC
)
GO 

这是预期的行为,但您建议采取什么行动以从我的方案中获得最佳性能?这里的主要观点是最佳表现。

1 个答案:

答案 0 :(得分:7)

为什么要为自己的观点编制索引?您在解决方案2中提到了“浪费空间”,但您是否知道在索引视图时,将其保留在数据库中?

换句话说,您复制了视图将在数据库上返回的数据,并且每次在源表上更新数据时,SQL Server的某些内部机制必须在创建的这个新数据结构上更新它。现在SQL服务器从视图中读取,而不是表格。

如果您使用Profiler + DTA甚至DMVS,您可以在表格中创建正确的索引,以便任何视图都能从中受益