7

我在我的数据库中有几个表(User & UserRecord),这些表得到极其分散的状态(如99%),并导致整个数据库因此导致网站崩溃。SQL Server碎片问题

UserRecord有点像用户在某个时间点的快照。用户就像该用户的主记录。用户有0到多个UserRecords。用户有大约一百万行,UserRecord有大约250万行。这些表格写得很多。他们也被搜查了很多。他们都会变得更大。变得非常分散的主要索引是User和UserRecord表的主键。

该数据库是SQL Server 2012年,我正在使用实体框架,我没有使用任何存储过程。

表是这个样子:

USER 
UserName string PK ClusteredIndex 
FirstName string 
LastName string 
+SeveralMoreRows 

USER_RECORD 
UserRecordId int PK ClusteredIndex 
ListId int FK(List) 
UserName string FK(User) NonClusteredIndex 
Community string NonClusteredIndex 
DateCreated datetime 
+LotsMoreRows 

LIST 
ListId int PK & ClusteredIndex 
Name string 
DateCreated datetime 

(不知道名单,这是重要的或没有,但想到我会包括它,因为它是关系到User_Record列表中包含了0到许多UserRecords。)

我们已经设置了SQL维护计划来每天重建索引,这有助于帮助,但有时还不够。

一位朋友建议我们使用两个数据库,一个用于读取,一个用于写入,并且我们同步从写入DB读取的数据库。并不是说我知道做这件事的任何事情,但我看到这个解决方案时遇到的第一个问题是我们在查看网站时需要最新的数据。例如,如果我们更新用户详细信息或UserRecord,我们希望立即看到这些更改。

有没有人有任何建议,我可以解决这个问题之前,它螺旋失控?

+0

什么是表格定义?你使用GUID作为主键吗? –

+0

你是否是唯一标识符列上的聚集索引?这往往会在一些插入后导致碎片...因为这些值是随机的... – PrfctByDsgn

+0

我在问题中添加了一些更多的细节 – Owen

回答

5

聚簇索引控制着磁盘上数据的顺序。这是通常建议您设置一个始终增加的整数键以充当聚簇索引的主要原因之一。这样,随着更多数据添加到表中,它们将被添加到当前现有数据的末尾。

如果它不是一个自动增加的数字,并且新行可能包含将在现有值之间的某个位置进行排序的值,那么SQL Server将基本上将数据推送到它所属的磁盘上(以保留聚簇索引键值的顺序),由于IO写入进一步减慢了数据库速度,因此产生碎片和潜在的严重开销。

我怀疑你的UserRecord值有同样的问题。

所以我要做的是为每个表添加一个单独的集群自动增长主键,并在必要时重新修改您的FK引用&查询。

+0

为什么不将PK索引声明为非集群? –

+0

通常最好在表上有一个聚集索引。即使你将其忽略并创建一个非聚集PK,它也会将该表存储为一个HEAP,其中还有其他一些问题。例如,对它运行的所有查询首先必须找到非聚簇索引匹配,然后从HEAP中查找匹配的行以获取其他值,因为它们不像聚簇索引那样容易。再次,产生不必要的开销减慢了数据库。 Google在HEAP和CLUSTERED表格上有几篇很好的文章。 – Kahn

+1

谢谢,听起来像SQL Server与其他DBMS(例如Postgres,Oracle)在索引方面有很大的不同。 –