Sql server SQL Server碎片问题

Sql server SQL Server碎片问题,sql-server,database,database-design,sql-server-2012,database-fragmentation,Sql Server,Database,Database Design,Sql Server 2012,Database Fragmentation,我的数据库中有两个表(User和UserRecord),它们非常零碎(比如99%),导致整个数据库和网站陷入停顿 UserRecord有点像那个用户在某个时间点的快照。用户就像该用户的主记录。用户有0到多个用户记录。用户大约有一百万行,UserRecord大约有250万行。这些表格写得很多。他们也被搜查了很多次。他们都会变得更大。严重碎片化的主要索引是User和UserRecord表的主键 数据库是SQL Server 2012,我使用的是实体框架,没有使用任何存储过程 表如下所示: USER

我的数据库中有两个表(User和UserRecord),它们非常零碎(比如99%),导致整个数据库和网站陷入停顿

UserRecord有点像那个用户在某个时间点的快照。用户就像该用户的主记录。用户有0到多个用户记录。用户大约有一百万行,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_记录相关。这个列表有0到多个userrecord)

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

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


有人对如何在问题失控之前解决这个问题有什么建议吗?

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

如果它不是一个自动递增的数字,并且新行可能包含在现有值之间排序的值,那么SQL Server基本上会将数据推送到它所属的磁盘上(以保留聚集索引键值的顺序),当IO写入进一步降低数据库速度时,会产生碎片和潜在的严重开销

我怀疑您的UserRecord值也有同样的问题


因此,我要做的是为每个表添加一个单独的聚集自动递增主键,并在必要时重新处理FK引用和查询。

表定义是什么?您是否使用guid作为主键?是否在uniqueidentifier列上具有聚集索引?这通常会导致插入后的碎片化。。。因为这些值是随机的……我在问题中添加了更多的细节,您是如何得出碎片导致问题的结论的?绝大多数的查询不会对特定的用户进行搜索吗?网站已被破坏,大多数查询正在超时,我们查看索引的碎片,它们高达99%,我们运行SQL Server索引重建/修复任务,一切又恢复正常了。为什么不将PK索引声明为非聚集索引呢?通常最好在表上有一个聚集索引。即使您不使用它并创建一个非集群PK,它也会将表存储为一个堆,这还存在许多其他问题。例如,针对它运行的所有查询首先必须找到非聚集索引匹配项,然后从堆中找到匹配行以获取其他值,因为它们不像聚集索引那样容易获得。同样,产生不必要的开销会降低DB的速度。Google有一些关于堆和集群表的好文章。谢谢,听起来SQL Server与其他DBMS(例如Postgres、Oracle)有着极大的不同在索引方面。增加填充因子并结合每日索引重建是否可以替代在用户表上添加自动递增的int主键?是的,您可以这样做,但不断增加的值通常是一个好主意。如果你有一个日期列,你可以用它来代替主键。您可以使用维护任务或自定义作业在sql server中每晚运行索引reorg或重建。