23

Вопрос по sql-server-2008, sql-server, sql – Индексированные просмотры и левые соединения раз и навсегда

Я использую MSSQL Server 2008 R2 и пытаюсь оптимизировать свои представления, когда наткнулся на индексированные представления. К сожалению, большинство моих видов используют левые внешние соединения, которые не поддерживаются в индексированных представлениях. После нескольких исследований я остался в замешательстве, как лучше всего это сделать. На мой взгляд, у меня есть следующие варианты:

1) Преобразуйте левые объединения во внутренние объединения, используя метод для имитации левого объединения с помощью команды «ИЛИ (IsNull (a) И IsNull (b))» & quot;

Я нашел это решение в нескольких местах, но было упоминание о потере производительности.

2) Преобразуйте левые объединения во внутренние объединения и замените пустые столбцы с пустыми направляющими (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)

Теперь, выполнив следующий запрос, мы получим & quot; Невозможно создать индекс для представления & quot; Test.dbo.v_Tags & quot; потому что он использует соединение LEFT, RIGHT или FULL OUTER, а соединения OUTER не допускаются в индексированных представлениях. Попробуйте вместо этого использовать INNER join. & Quot ;:

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

Это ожидаемое поведение, но какой образ действий вы бы порекомендовали, чтобы получить максимальную производительность из моего сценария? Главная точка здесь - лучшая производительность.

  • Вы также должны проиндексировать свое представление, если вы хотите создать полнотекстовый индекс для него.

    от
  • Что если представление представляет почти постоянные данные (редко изменяемые в базовых таблицах) и также используется во многих местах? Индексированное представление очень помогает для производительности в этом случае

    от
  • в таком случае да. Вы правы

    от
  • Я ответил на очень похожий вопрос о материализации индексов на левых соединениях. Хотя прямого способа сделать это не существует ... есть вариант № 5stackoverflow.com/a/31171129/1902664

    от cocogorilla
  • Столкнувшись с аналогичной ситуацией, денормализованная таблица (с триггерами или каким-либо другим способом ее обновления) также может быть вариантом в списке.

    от Alex M
  • Что вы в итоге сделали с этим? Я сталкиваюсь с подобной проблемой, пытаясь проиндексировать некоторые взгляды.

    от user1948635
  • 7

    Почему вы индексируете свои взгляды? Вы упомянули «пустая трата простр

    анства» в вашем решении 2, но знаете ли вы, что когда вы индексируете свое представление, вы сохраняете его в БД?

    Другими словами, вы делаете копию данных, которые представление вернуло бы в БД, и каждый раз, когда данные обновляются в исходных таблицах, некоторый внутренний механизм SQL Server должен обновлять их в этой новой структуре данных, созданной, потому что теперь SQL-сервер читает из представления, а не из таблиц больше.

    Если вы используетеProfiler + ДТА или дажеDMVs вы можете придумать правильные индексы, которые будут созданы в ваших таблицах, которые выиграют от любого представления