如果它是一个堆,一个表会受益吗

Fre*_*gen 7 sql-server clustered-index index-tuning heap sql-server-2012

我有一个大约有 1.500.000 行的日志记录表,主键是一个升序标识,聚集索引在主键上。标识值是自动生成的 => 记录总是添加在最后。平均行大小为 1570 字节。

由于频繁添加新行,因此有很多页面拆分。没有行被更新/删除,并且表上有一个非聚集索引,因此可以选择行。由于页面拆分,聚集索引总是碎片化 > 65%。

我想知道我的表是否会因删除聚集索引并使其成为堆表而受益?

这是我的表 + 非聚集索引的样子:

CREATE TABLE [dbo].[LogEntry](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[Application] [varchar](20) NOT NULL,
[EntityFullName] [varchar](80) NOT NULL,
[Action] [int] NOT NULL,
[UserName] [varchar](25) NOT NULL,
[TimeStamp] [datetime] NOT NULL,
[EntityId] [varchar](50) NOT NULL,
[WhatChanged] [nvarchar](max) NULL,
CONSTRAINT [PK_LogEntry] PRIMARY KEY CLUSTERED(     
   [Id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 100) ON [PRIMARY] ) 
ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]


CREATE NONCLUSTERED INDEX [ID_Application_Entity_FullName_TimeStamp] ON [dbo].[LogEntry]
(
    [Application] ASC,
    [EntityFullName] ASC,
    [TimeStamp] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = OFF) ON [PRIMARY]
GO
Run Code Online (Sandbox Code Playgroud)

更新: 有人在我背后启用了自动收缩 => 这将是碎片的原因

Ken*_*her 5

这开始是一个评论/问题,但时间很长,所以我把它移到了这里:

我真的被这个问题所困扰。150 万行并不是那么大。身份背后的要点是它在不断增加。如果那是您的 CL,您不应该在页面中间插入,当然不会经常导致您看到的碎片级别。

几个问题:

你在做 IDENTIY_INSERTS 吗?基本上指定身份值应该是什么?或者您是否在某个时候重新设置了身份,以便插入范围的中间?

通常,如果您正在执行插入操作,它看起来像这样:

5 6 7 8 < Next insert goes here >
Run Code Online (Sandbox Code Playgroud)

但是如果你有这样的东西(假设你的下一个身份值为 4)

 1 2 3 < Next insert goes here > 100 101  
Run Code Online (Sandbox Code Playgroud)

然后你可能会看到很多页面拆分。但在正常情况下,你不应该这样做。

您是否有可能缩小数据库? Auto_shrink或者一个会缩小的维护计划/工作?如果是这样,则是缩小导致您的碎片而不是聚集索引。

一般来说,HEAP 没有任何问题,并且它们对于 INSERT 来说可以更快。我对它们最大的担忧往往是您是否正在执行大量删除或更新(您说不是)。在这些情况下,您可能会出现空间泄漏并最终得到一个大小为多 GB 但有 0 行的表。

实际答复

鉴于您有一个日志文件,并且只是插入,您可以尝试删除 PK 并查看性能如何(当然首先在测试环境中)。一旦您使用您的工作负载运行了一些测试并查看情况如何,然后在生产中进行更改并在那里监控一段时间。您甚至可以考虑完全删除标识列。

不过,请检查一下 SHRINK 的东西。那是个杀手。