回答

收藏

一劳永逸的索引视图和左联接

技术问答 技术问答 256 人阅读 | 0 人回复 | 2023-09-14

我正在使用MSSQL Server 20084 W4 {& p- ^" ~4 v4 k
R2,当我偶然发现索引视图时,我正在尝试优化视图。不幸的是,我的大多数视图都使用左外部联接,而索引视图不支持这种联接。经过一堆研究,让我感到困惑的是最好的解决方法。我看到的方式有以下几种选择:
* K. }' @# d0 ~$ [3 u# z1) 使用技巧将左联接转换为内部联接,以使用“ OR(IsNull(a)AND IsNull(b))”模拟左联接  @* e5 `% z+ H7 B
我在几个地方找到了该解决方案,但是提到了性能下降。
2 u# d% P  q! F1 `/ V) \2 _. o2)
6 b$ S% K9 u; ]& }, \将左联接转换为内联接,并用空的GUID(00000000-0000-0000-0000-0000-000000000000)替换可为空的列的空值,并在右表中添加一个具有匹配GUID的单行。. M0 j4 B. p4 j0 d1 m" s8 f6 F! S
这似乎是最明显的性能方法,但似乎浪费了每行否则将为NULL的空间。
7 @' z- c# y8 x$ A+ B3)将 我的观点分为两个观点。第一个观点是我的大多数可索引逻辑。第二个视图是从第一个视图派生而来的,并添加了左连接。
1 E! e' Q. X/ q) l% F这里的想法是,通过索引基础视图可能会提高性能。而且即使查询派生视图也将至少获得一些性能上的好处。# U8 v5 F$ y* [3 T5 G1 Q+ p& j2 L
4) 不要索引我的观点7 m6 {" N) \. d. `
会以比以上任何一种方法都更有效的方式离开视图吗?& P) y5 Z8 n9 L. c: o2 H0 M7 [8 e  b
5) 我没想到的想法& k* A/ }- Z3 b- @% F
我编写了以下基本脚本:
& h$ O! m" ?) U( W/ Z) i- @: z   CREATE TABLE [dbo].[tbl_Thumbnails]($ L3 b( I8 e/ Q8 s1 s7 `: @) ?
        [ThumbnailId] [uniqueidentifier] NOT NULL,
7 b7 n( D6 t7 ~# r3 u! m        [Data] [image] NULL,
8 |7 o7 r- w2 j: N3 M2 }        [Width] [smallint] NOT NULL,, g' B* T9 A7 e! ^0 ~, o
        [Height] [smallint] NOT NULL" z/ o0 x5 Y- m; z7 \! f
     CONSTRAINT [PK_tbl_Thumbnails] PRIMARY KEY CLUSTERED 9 ^/ B. ?! d% B. `) g% ]
    (
3 ]  i/ Q# i; ~9 X1 o4 i- [        [ThumbnailId] ASC
2 @" ~& o' n2 Q! ^' y    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ~$ g. C9 c# ?- i    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]' C, W. T( E6 w2 A
    GO% j! y  f2 s- G2 U+ V7 H
    CREATE TABLE [dbo].[tbl_Tags](! e# h( X; R8 P6 v
        [TagId] [uniqueidentifier] NOT NULL,
* }, {8 {% u" ?. M3 W$ ~        [ThumbnailId] [uniqueidentifier] NULL' ]0 d3 V6 J1 U2 M9 `
     CONSTRAINT [PK_tbl_Tags] PRIMARY KEY CLUSTERED   w# I* L% E& i1 ~
    (
; B2 V$ D+ @/ g7 [/ p" e0 s4 I+ q$ A( l        [TagId] ASC
6 M5 a8 f# j1 t4 s5 C, c, n    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
/ K7 E8 [* A3 h6 m    ) ON [PRIMARY]
% X- O# _$ R1 ?9 j    GO+ T" K% M5 a$ J1 N7 @8 p# s9 x" W
    CREATE VIEW [dbo].[v_Tags] WITH SCHEMABINDING AS. o" @% ?9 R$ q: @7 V4 F
    SELECT     dbo.tbl_Tags.TagId, dbo.tbl_Tags.ThumbnailId- v6 F0 H  V0 b. Q6 V- ]" \5 i6 t
    FROM         dbo.tbl_Tags LEFT OUTER JOIN
8 v2 h/ D. h5 w- o& J                          dbo.tbl_Thumbnails
5 M1 `% x, n$ x# Z+ V' b  q    ON     dbo.tbl_Tags.ThumbnailId = dbo.tbl_Thumbnails.ThumbnailId' B+ q' d* N6 n  B! U
    GO
/ Y9 e" C- |& C$ ~8 R( H9 I5 T' u* b    INSERT INTO tbl_Tags VALUES ('16b23bb8-bf17-4784-b80a-220da1163584', NULL)
7 B: L. b3 q- G' I* L    INSERT INTO tbl_Tags VALUES ('e8b50f03-65a9-4d1e-b3b4-268f01645c4e', 'a45e357b-ca9c-449a-aa27-834614eb3f6e')7 n; E: x$ ?" j- o) e
    INSERT INTO tbl_Thumbnails VALUES ('a45e357b-ca9c-449a-aa27-834614eb3f6e', NULL, 150, 150)
" r" q! h* s. T7 C现在,执行以下查询将产生“无法在视图“ Test.dbo.v_Tags”上创建索引,因为它使用LEFT,RIGHT或FULL
1 B+ y4 A6 u9 U" W9 P0 E8 ^' WOUTER联接,并且索引视图中不允许使用OUTER联接。请考虑使用INNER联接。 ”:7 {# F7 J2 a3 q0 F  E
CREATE UNIQUE CLUSTERED INDEX [TagId] ON [dbo].[v_Tags] & Y; h+ X8 y; g+ t, ~8 b
(
) D6 B8 N; q( Y% J1 s[TagId] ASC7 j* T2 r. |9 S2 L9 s, U
)3 g6 H/ B- _% V, \. |+ G
GO
: r. Y- ~8 T0 F- }这是预期的行为,但是您建议采取什么措施才能从我的方案中获得最佳性能?这里带回家的地方是最好的性能。
5 H. V6 M, L8 M, {: R% {& R! j                  o; W9 l9 `* _0 |5 u& y% d( G0 F
解决方案:
8 W* `7 O! U4 K: o               
5 D, t* W) y% o$ O/ S( {
; ^. J% G4 o! T. S% }) K8 d9 b9 q3 f) a7 L7 U/ q6 N- K1 Q
                为什么要索引您的视图?您在解决方案2中提到了“空间浪费”,但是您是否知道在索引视图时将其持久保存在数据库中?
6 k8 q2 t3 K! ]+ w; B/ T换句话说,您需要复制视图将在数据库上返回的数据的副本,并且每次在源表上更新数据时,SQL
3 {. e+ h& H7 \' `% @) t& @9 y( _Server的某些内部机制都必须在创建的这个新数据结构上对其进行更新,因为现在SQL Server从视图中读取,不再从表中读取。1 G+ A; g# W5 r* `8 Q4 {
如果您使用Profiler +
2 c% i1 s7 q: j/ W2 g  g# [: SDTA甚至DMVS,则可以在表上提供要创建的正确索引,任何视图都将从中受益
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则