【问题标题】:Indexed Views and Left Joins once and for all索引视图和左连接一劳永逸
【发布时间】:2012-04-20 03:11:56
【问题描述】:

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

1) 使用“OR (IsNull(a) AND IsNull(b))”模拟左连接的技巧将左连接转换为内连接

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

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

这似乎是最明显的性能方面,但它似乎浪费了每一行本来会是 NULL 的空间。

3) 把我的观点分成两个观点。第一个视图是我可索引的大部分逻辑。第二个视图派生自第一个视图并添加左连接。

这里的想法是,通过索引基本视图可能会提高性能。而且即使查询派生视图也至少会获得一些性能优势。

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 

这是预期的行为,但您会建议采取什么行动来从我的方案中获得最佳性能?这里的重点是最佳性能。

【问题讨论】:

  • 你最后做了什么?我在尝试为某些视图编制索引时遇到了类似的问题。
  • 面对类似的情况,非规范化表(使用触发器或其他保持其最新的方式)也可能是列表中的一个选项。
  • 我回答了一个关于在左连接上实现索引的非常相似的问题。虽然没有直接的方法...这里是选项 #5 stackoverflow.com/a/31171129/1902664

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


【解决方案1】:

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

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

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

【讨论】:

  • 如果视图呈现几乎不变的数据(在基础表中很少更改)并且在许多地方也使用了怎么办?在这种情况下,索引视图有助于提高性能
  • 如果要在视图上创建全文索引,还必须对其进行索引。
猜你喜欢
  • 1970-01-01
  • 2016-07-20
  • 2017-06-16
  • 1970-01-01
  • 2016-03-20
  • 2016-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多