Cra*_*aig 96 sql indexing performance sql-server-2008
我对SQL(Server 2008)的较低级别知识是有限的,现在由我们的DBA挑战.让我解释一下(我已经提到了明显的陈述,希望我是对的,但如果你看错了,请告诉我)情景:
我们有一张桌子可以为人们提供"法院命令".当我创建表(Name:CourtOrder)时,我创建了它:
CREATE TABLE dbo.CourtOrder
(
CourtOrderID INT NOT NULL IDENTITY(1,1), (Primary Key)
PersonId INT NOT NULL,
+ around 20 other fields of different types.
)
Run Code Online (Sandbox Code Playgroud)
然后,我将非聚集索引应用于主键(以提高效率).我的理由是它是一个唯一的字段(主键),并且应该像我们经常那样被索引,主要用于选择目的Select from table where primary key = ...
然后我在PersonId上应用了CLUSTERED索引.原因是在物理上对某个人进行分组,因为绝大多数工作都是为了获得一个人的订单.所以,select from mytable where personId = ...
我现在已被拉上了这个.有人告诉我,我们应该将聚簇索引放在主键上,将正常索引放在personId上.这对我来说似乎很奇怪.首先,为什么要在特殊列上放置聚簇索引?什么是聚类?当然这是浪费聚集索引?我相信一个普通的索引会用在一个独特的列上.此外,聚类索引意味着我们不能聚集不同的列(每个表一个,对吧?).
我被告知我犯了一个错误的原因是他们认为在PersonId上放置聚集索引会使插入变慢.对于选择速度增加5%,我们将在插入和更新时降低95%的速度.这是正确有效的吗?
他们说因为我们聚集了personId,所以当我们插入或更改PersonId时,SQL Server必须重新排列数据.
那么我问过,为什么SQL会有一个CLUSTERED INDEX的概念,如果它这么慢?它和他们说的那么慢吗?我应该如何设置索引以获得最佳性能?我以为SELECT比INSERT更多......但他们说我们在INSERTS上遇到了锁定问题......
希望可以有人帮帮我.
Ada*_*son 116
聚簇索引与非聚簇索引之间的区别在于聚簇索引确定数据库中行的物理顺序.换句话说,应用聚簇索引PersonId
意味着行将PersonId
在表中进行物理排序,允许对此进行索引搜索直接到行(而不是非聚集索引,这将指向行的位置,增加一个额外的步骤).
也就是说,主键不是聚集索引是不寻常的,但并非闻所未闻.您的方案的问题实际上与您假设的相反:您希望聚簇索引中的唯一值,而不是重复.由于聚簇索引确定行的物理顺序,因此如果索引位于非唯一列上,则服务器必须向具有重复键值的行添加背景值(在您的情况下,任何具有相同键的行)PersonId
)使组合值(键+背景值)是唯一的.
我唯一建议的不是使用代理键(您的CourtOrderId
)列作为主键,而是使用复合主键PersonId
和其他一些唯一标识列或列集.但是,如果那不可能(或不实用),那么就把聚集索引放在上面CourtOrderId
.
Dar*_*ler 14
我绝不是SQL专家......所以把它作为开发人员的视图而不是DBA视图.
在不按顺序排列的集群(物理排序)索引上插入会导致插入/更新的额外工作.此外,如果您同时发生多次插入并且它们都发生在同一位置,则最终会出现争用.您的具体表现会因您的数据以及访问方式而异.一般的经验法则是在表中最独特的窄值上构建聚簇索引(通常是PK)
我假设你的PersonId不会改变,所以更新不会在这里发挥作用.但考虑一下PersonId为1 2 3 3 4 5 6 7 8 8的几行快照
现在为PersonId为3插入20个新行.首先,由于这不是唯一键,服务器会在您的值(幕后)中添加一些额外的字节以使其唯一(这也会增加额外的空间),然后是位置这些将驻留必须改变.将其与插入自动递增PK进行比较,其中插入发生在最后.非技术性的解释可能归结为:如果在表格末尾自然进展较高的值而不是在插入项目时在该位置重新处理现有项目的位置,那么"叶子改组"的工作就会减少.
现在,如果您遇到插入问题,那么您可能会同时插入一堆相同(或类似)的PersonId值,这会导致整个表中各个位置的额外工作,并且碎片会导致您死亡.在你的情况下转换到PK聚集的缺点是,如果你今天在PersonIds上有插入问题,如果你将聚簇索引切换到PK并且所有插入现在都在一个由于争用集中度增加,您的问题实际上可能会变得更糟.(另一方面,如果你今天的插页没有全部展开,但通常都是在类似的区域内聚集,那么你的问题可能会通过将聚集索引从PersonId切换到你的PK来缓解,因为你将最小化碎片.)
应根据您的独特情况分析您的性能问题,并仅将这些类型的答案作为一般指导原则.您最好的选择是依靠DBA来准确验证问题所在.听起来你有资源争用问题可能超出简单的索引调整.这可能是一个更大问题的症状.(可能的设计问题......否则资源有限.)
无论如何,祝你好运!
一些学者也建议不要"浪费"的CI
上identity
栏,如果有,将有利于范围查询的替代品.
根据MSDN 聚集索引设计指南,应根据以下标准选择密钥
你的CourtOrderID
专栏符合2
.你的PersonId
见面1
和3
.因为大多数行最终会uniqueifier
添加添加,你也可以将它声明为唯一并使用,PersonId,CourtOrderID
因为这将是相同的宽度但更有用,因为聚集索引键被添加到所有NCI作为行定位器,这将允许它们可以涵盖更多查询.
使用PersonId,CourtOrderID
CI作为CI 的主要问题是可能会出现逻辑碎片(这尤其会影响您尝试帮助的范围查询),因此您需要更频繁地监视填充因子和碎片级别并执行索引维护.