标签: clustered-index

将聚集索引添加到其他人应用程序上的 HEAP 表

我们正在使用基于 SQL Server 2005 的专有应用程序,它有许多基于 HEAP 的表(即没有聚集索引)。多年来,这些表变得非常碎片化(例如 99% 碎片化)。我需要对它们进行碎片整理。

现在,在 SQL Server 2005 中,没有办法直接做到这一点。我可以:

  1. 在先前存在的字段上创建聚集索引,并保留它
  2. 创建该索引,重建表,然后删除它
  3. 添加我自己的字段(例如自动增量键)

现在,这是一个由供应商编写的大型应用程序——一个巨大的黑匣子。我并不急于弄乱他们的东西。我不太了解这些表是如何使用的。这样做的影响最小的方法是什么?

而且,作为后续:有许多这些基于 HEAP 的表,应用程序使用了十多个数据库。有没有办法自动选择 #2 或 #3?或者,我应该如何选择要修改的表?


更新:
回答(非常有帮助的)回复提出的问题:

  • 性能是不可接受的。供应商告诉我的客户他们这是因为表非常碎片化,客户有责任定期对它们进行碎片整理
  • 我们有两个应用程序实例:测试实例和生产实例
  • 我首先对所有 Clustered 表进行了碎片整理,这大大提高了性能
  • 供应商的支持团队非常没有帮助。他们告诉我们整理表格是我们的责任。当我问他们如何建议对基于 HEAP 的表进行碎片整理时 - 我应该添加聚集索引吗?- 他们只回答“这是微软的问题”。

简而言之,客户支持团队已经明确表示:您必须对表格进行碎片整理,如何做是您的事。

至于未来的版本:是的,新版本正在开发中,最终会迁移到 SQL Server 2012。但是他们今天需要性能解决方案。

最后,至于碎片整理时间太长:没关系。他们有 99% 碎片化的巨型表;该应用程序不在夜间使用;我可以轻松地一次花费数小时对它们进行碎片整理。

performance sql-server optimization clustered-index index-tuning

7
推荐指数
2
解决办法
1883
查看次数

集群表与非集群表

碰巧我不得不同时使用 SQL Server 和 Oracle 很长一段时间(幸好不是同时使用)。

仍然让我困惑的是将表存储为平衡树的方法。在类似 Oracle 的 RDMS 堆中是默认的,在 SQL Server(和许多其他)中,相反(集群,IOT)是真实的。每种方法的专家都声称他们的方法是唯一“正确”的,并支持通过大量测试/演示选择的观点。但是,在我看来,他们证明的唯一一点是“非默认”方法的实施很差,并且不应该用于大多数情况......

我很确定这两种方法都足够好(只是因为它们仍然存在于市场上并且表现出相当的性能)并且下面有一些数学运算,但是我没有找到任何好的参考。

我意识到这个话题可能太宽泛而无法回答,非常欢迎好的链接,但我真的很想知道为什么两种看似有争议的方法都证明它们都是有效的。

clustered-index

7
推荐指数
1
解决办法
2857
查看次数

SQL Server 聚集索引、索引平衡和使用 NewID 的插入性能

我有一个大(6db)的跟踪表。它有一个通过 GETDATE() 创建的聚集键 (DateTime)。

连接到这个数据库/表的连接池在 10 台计算机的集群中平均上升到 50,因此平均我们有大约 500 个并发连接尝试插入。

数据库适合内存,几乎看不到任何 IO。

我试图弄清楚在持续的 INSERT 负载下,聚集索引是否会达到重新平衡树的程度,以及这是否会导致系统可以维持的插入次数减慢。

关于重新平衡索引是否是 SQL Server 对聚集索引(甚至是非聚集索引)执行的操作,我有一些疑问。

问题-

  1. 是否有任何原因导致插入性能的周期性/循环放缓?
  2. 重新平衡操作会自动触发聚集索引吗?
  3. 重新平衡操作会在非聚集索引上自动触发吗?

其他信息

  • SQL Server 2008
  • 真正的大型服务器 - 256Gb、40 核、40mbit LAN...

performance sql-server clustered-index insert nonclustered-index

7
推荐指数
2
解决办法
1635
查看次数

聚集索引帮助,我哪里出错了?

我被要求查看一张非常繁忙的表格并找出任何需要改进的地方。
我只能更改索引表的能力非常有限。

表信息

  • 240 列
  • 约 500 万行
  • 由大约 30 个应用程序阅读和更新,范围从网站到投票应用程序。
  • 每行代表一个合约及其基于三个标志(大小为 5、8 和 8 的 varchars)的状态。
  • 一行的生命周期通过这三个标志从开始到结束,最终完成。
  • 在整个生命周期中,一行通常会更新或更改 10 到 30 次。
  • 主键是 id 列、guid 列和 company 列的组合。
  • 表有 40 多个索引,其中大部分是重复的和未使用的。这是基于sys.dm_db_index_usage_statsDMV,在过去 7 周内每周运行两次。

此表上的当前聚集索引有五列:

  1. 公司列(50 个不同的值)
  2. 区域列(21 个不同的值)
  3. FlagA 列(8 个不同的值)
  4. FlagB 列(24 个不同的值)
  5. FlagC 列(5 个不同的值)

我的理解是聚簇索引应该坚持以下属性。 来源

  1. 独特的
  2. 静止的
  3. 狭窄的
  4. 不断增加。

当前的聚集索引不是这些。

  1. 没有唯一的 ID。
  2. 这三个标志不断更新。
  3. 任何给定时刻都可以有 5000 行所有 5 列都具有相同的值。

所以我的假设是用Id列上的聚集索引来纠正这个问题- 一个不是身份但通过计数器表维护的整数(读取值,加 1,更新计数器表)。

我在 上创建了一个聚集索引Id,不使用主键,因为我相信添加 guid 和 company 列不会给我任何好处。

然后我创建了一个非聚集索引,其中包含 …

sql-server clustered-index sql-server-2008-r2 index-tuning

7
推荐指数
1
解决办法
148
查看次数

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

我有一个大约有 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] …
Run Code Online (Sandbox Code Playgroud)

sql-server clustered-index index-tuning heap sql-server-2012

7
推荐指数
1
解决办法
1290
查看次数

将聚集主键转换为非聚集主键并使用另一列作为聚集索引

我有一个带有主键 (GUID) 的大表,它也是聚集索引。已经有一个基于整数序列的字段。所以我想保留 GUID 作为 PK 并使整数列成为聚集索引。

除了删除原始约束并创建新的 PK 和新的聚集索引之外,我想不出任何方法来做到这一点。但这需要很长时间,从我收集的内容来看,重建表两次,一次是从聚集索引转到堆,然后堆回到聚集索引。

我无法进行表重建(创建新的、迁移数据、交换名称),因为我不能中断。

有任何想法吗?

版本:SQL Server 2008 Service Pack 2,开发人员/企业。

index sql-server-2008 database-design sql-server clustered-index

6
推荐指数
1
解决办法
2186
查看次数

宽聚集索引与多个窄非聚集索引?

假设我有一个Student像这样的人为表:

CREATE TABLE Student (
    Id IDENTITY INT,
    SchoolId INT NOT NULL,
    FirstName VARCHAR(20) NOT NULL,
    LastName VARCHAR(20) NOT NULL
)
Run Code Online (Sandbox Code Playgroud)

本能地,我会制作Id主键(以及聚集索引)。但是,我会发现自己在搜索,SchoolId因此我会在SchoolId.

这与主键(和聚集索引)相比如何SchoolId, Id?我将始终拥有SchoolIdif 我需要搜索 by Id,所以无论如何我都会使用聚集索引,如果我只需要搜索 by SchoolId,记录将在物理上彼此相邻。

如果我要进行任何类型的搜索或批量更新,它们会在SchoolId特定记录上,例如找到所有带有姓名/号码/任何内容的孩子SchoolId。我永远不会SchoolId在同一事务中跨多个s执行这些类型的操作。让这些记录在物理上彼此相邻的好处是否使这种方法比简单地在 上使用聚集索引要好得多Id

使用后者有很大的缺点吗?我还是个新手,有很多主题我还没有完全理解(例如碎片化)以及它如何影响这种情况。

sql-server clustered-index index-tuning physical-design nonclustered-index

6
推荐指数
1
解决办法
835
查看次数

在不删除主键的情况下更改聚集索引

过去,我选择创建datetime列作为表中不合适的聚集索引。

现在我得出结论(基于执行计划)选择 ID身份主键作为聚集键会更好,因为它经常被作为外键引用。

我想删除当前的聚集键并创建一个新的,但我不能删除主键,因为full-text索引依赖于该主键。

我可以将主键切换为聚集索引还是需要删除主键和所有依赖对象的链?

下面你会找到表定义和聚集索引定义。

CREATE TABLE [dbo].[Realty](
    [Id] [int] IDENTITY(1,1) NOT NULL,  
    [Created] [datetime] NOT NULL,
    ....

 CONSTRAINT [PK_Realty] PRIMARY KEY NONCLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
...


CREATE CLUSTERED INDEX [Created] ON [dbo].[Realty]
(
    [Created] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE …
Run Code Online (Sandbox Code Playgroud)

foreign-key sql-server primary-key clustered-index full-text-search

6
推荐指数
1
解决办法
2万
查看次数

当 Azure 推荐包含所有其他列的索引(自然键的一部分)时,我是否应该为此自然键切换到聚集索引?

该表确实有一个身份密钥(当前 CI),但它几乎不用于查询。因为自然键不会不断增加,所以我担心插入性能、碎片或其他我现在无法预见的问题。

桌子并不宽,只有几列。它有大约 800 万行,并且在高峰时段使我们的网站停止运行。(+1000s 并发用户)。数据不容易缓存,因为它非常不稳定并且必须保持最新状态。

自然键的一列有很多读取,但插入和更新也相当活跃。说 8 次读取,1 次更新 vs 1 次插入。

Id (PK)         int
UserId*         int
Key1*           varchar(25)
Key2*           varchar(25)
Key3*           int
LastChanged     datetime2(7)
Value           varchar(25)
Invalid         bit

* this combination is the natural primary key
Run Code Online (Sandbox Code Playgroud)

我大部分时间都需要查询:

  • 一个 UserId 的所有行(查询最多)
  • UserIds 列表的所有行(很多行)
  • Key1 = X 的 UserIds 列表的所有行
  • Key2 = X 的 UserIds 列表的所有行
  • Key1 = X 和 Key2 = X 的 UserId 列表的所有行

我知道最终的答案总是“描述它”,但我们在这里的时间非常有限,因此我们非常感谢您提前提供任何指导或有经验的意见。

提前致谢,

performance sql-server clustered-index

6
推荐指数
1
解决办法
116
查看次数

大表的在线索引重建需要排他锁

我正在尝试在 Azure SQL 数据库上重建大表 (77GB) 的聚集索引。表上有高并发事务活动,因此我正在使用该ONLINE=ON选项。

这对于较小的表很有效;但是,当我在这个大表上运行它时,它似乎在表上使用了排他锁。我不得不在 5 分钟后停止它,因为所有事务活动都超时了。

来自 SPID 199 的会话:

ALTER INDEX PK_Customer ON [br].[Customer] 
REBUILD WITH (ONLINE = ON, RESUMABLE = ON);
Run Code Online (Sandbox Code Playgroud)

从另一个会话:

CL

在相同的结果中更进一步:

在此处输入图片说明

  • 对象 978102525 是聚集索引。
  • 对象 1125579048 是表。

在此处输入图片说明

我知道在线重建可以在过程开始和结束时锁定“短”持续时间。但是,这些锁定会持续几分钟,这并不完全是“短”持续时间。

附加信息

在重建运行时,我运行了SELECT * FROM sys.index_resumable_operations;但它返回了 0 行,就好像重建根本没有开始一样。

较小的表也有一个可能大于 900 字节的 PK,并且相同的ALTER语句在没有任何长时间阻塞的情况下工作,所以我认为它与 PK 大小无关。这些较小的表也有相似数量的nvarchar(max)列。我能想到的唯一真正的区别是这个表有更多的行。

表定义

这是 的完整定义br.Customer。没有外键或非聚集索引。

CREATE TABLE [br].[Customer](
    [Id] [bigint] NOT NULL,
    [ShopId] [nvarchar](450) NOT NULL,
    [accepts_marketing] [bit] NOT NULL,
    [address1] [nvarchar](max) MASKED WITH …
Run Code Online (Sandbox Code Playgroud)

sql-server clustered-index azure-sql-database index-maintenance online-operations

6
推荐指数
1
解决办法
460
查看次数