我有一张大桌子(在74到8800万行之间),这是多对多关系的中间表(表B)。我有一个视图,可以构建这些表中包含的数据的统一图片。视图具有针对它定义的聚簇索引。
我的大表左侧的表A是我数据库中的核心表。表C是包含规范化数据项的表。当我将新记录插入表C时,任务需要很长时间才能完成(在非常好的服务器上5分钟)。这是因为SQL Server在视图上重建了聚集索引的一部分(我可以在实际执行计划中看到聚集索引插入)。尽管表C中没有引用表C中的新行,但是如表所示,将行插入表A和表B中需要毫秒。数据库未分区。
这是表创建脚本的恼人版本。我已经离开了未使用的列,因此您可以看到表格的完整结构。
CREATE TABLE [dbo].[TableA] (
[TableAId] [INT] IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED ,
[TableAIdGUID] [uniqueidentifier] NOT NULL,
[ImportantId] [INT] NOT NULL ,
[DateCreated] [datetime] NOT NULL ,
[OtherId2] [int] NOT NULL ,
[TableATypeId] [int] NOT NULL ,
[Active] [bit] NOT NULL ,
[AuditUser] [NVARCHAR] (20) NULL ,
[AuditTime] [datetime] NULL
)
GO
CREATE TABLE [dbo].[TableB] (
[TableBId] [INT] IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED ,
[TableBGUID] [uniqueidentifier] NOT NULL,
[TableAId] [INT] NOT NULL ,
[TableCId] [INT] NOT NULL ,
[Tag] [NVARCHAR] (50) NULL ,
[Order] [tinyint] NOT NULL ,
[DateCreated] [datetime] NOT NULL ,
[Date1] [datetime] NULL ,
[Date2] [datetime] NULL ,
[LastUpdated] [datetime] NOT NULL ,
[Active] [bit] NOT NULL ,
[AuditUser] [NVARCHAR] (20) NULL ,
[AuditTime] [datetime] NULL
)
GO
CREATE TABLE [dbo].[TableC] (
[TableCId] [INT] IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED ,
[TableCIdGUID] [uniqueidentifier] NOT NULL,
[TableCTypeId] [int] NOT NULL ,
[TableCValue] [NVARCHAR] (255) NOT NULL ,
[Frequency] [float] NOT NULL DEFAULT 1,
[TableCValue2] [NVARCHAR] (255) NULL ,
[AuditUser] [NVARCHAR] (20) NULL ,
[AuditTime] [datetime] NULL
)
GO
CREATE VIEW [dbo].[vwTables]
WITH SCHEMABINDING ,ENCRYPTION
AS
SELECT dbo.[TableB].TableBId,
dbo.[TableB].TableAId,
dbo.TableA.ImportantId,
dbo.TableC.TableCValue,
dbo.TableC.TableCValue2,
dbo.TableC.TableCTypeId,
dbo.TableA.TableATypeId
FROM dbo.[TableB] INNER JOIN
dbo.TableC ON dbo.[TableB].TableCId = dbo.TableC.TableCId INNER JOIN
dbo.TableA ON dbo.[TableB].TableAId = dbo.TableA.TableAId
WHERE (dbo.[TableB].Active = CAST(1 AS BIT)) AND (dbo.TableC.TableCValue<>'') and (dbo.TableC.TableCValue is not null)
GO
CREATE UNIQUE CLUSTERED INDEX [IX_vwTables] ON [dbo].[vwTables]
(
[TableCValue] ASC,
[TableCTypeId] ASC,
[TableBId] ASC,
[ImportantId] ASC
)
GO
ALTER TABLE [dbo].[TableB] ADD
CONSTRAINT [FK_TableB_TableC] FOREIGN KEY
(
[TableCId]
) REFERENCES [dbo].[TableC] (
[TableCId]
),
CONSTRAINT [FK_TableB_TableA] FOREIGN KEY
(
[TableAId]
) REFERENCES [dbo].[TableA] (
[TableAId]
)
GO
CREATE NONCLUSTERED INDEX [IX_TableA_Nonclustered] ON [dbo].[TableA]
(
[ImportantId] ASC,
[TableAId] ASC,
[TableATypeId] ASC,
[Active] ASC
)
GO
CREATE NONCLUSTERED INDEX [IX_TableA_OtherId2] ON [dbo].[TableA]
(
[AuditTime] ASC,
[OtherId2] ASC
)
GO
CREATE NONCLUSTERED INDEX [IX_TableB_NonClustered] ON [dbo].[TableB]
(
[TableAId] ASC,
[TableBId] ASC,
[Active] ASC
)
GO
CREATE NONCLUSTERED INDEX [IX_EntityAttributes_NonClustered_2] ON [dbo].[TableB]
(
[TableBId] ASC,
[TableAId] ASC,
[TableCId] ASC,
[Tag] ASC,
[Active] ASC
)
GO
针对此运行的示例查询如下。
SELECT Query.ImportantId
FROM(
SELECT b.ImportantId
FROM [vwTables] a WITH (NOLOCK)
INNER JOIN [vwTables] b WITH (NOLOCK, NOEXPAND) ON a.TableCValue = b.TableCValue
WHERE a.ImportantId = @ImportantId AND
a.TableATypeId=3 AND b.TableATypeId=3
) As Query
GROUP BY Query.ImportantId
是否有人知道我如何能够(几乎)瞬间发生表C中的插入,就像插入TableA和TableB一样?
答案 0 :(得分:3)
如果我理解正确,您在视图上有聚集索引。当SQL Server发现视图下方的表发生更改时,它必须重新索引视图。这仅在表很少更改时才适用(想想商业智能数据库。)
考虑从视图中删除索引,并支持基础表上带索引的视图。
例如,请参阅MSDN中的this quote:
Q值。我一次更新我的数据仓库 周。索引视图加快了我的速度 在一周内查询了很多,但是 减慢每周更新?什么 我该怎么办?
一个。考虑删除索引视图 在每周更新和创建之前 他们之后再次。
编辑:您的示例查询似乎在A中搜索共享TableCValue的行。我认为它会受益于这些指数:
使用这些索引,您希望查询足够快,不需要索引视图。
P.S。在我遗漏某些内容时,请务必将我的建议与SQL Server Profiler中的索引建议进行比较。