SQL Server中非常大的表

时间:2009-03-24 13:50:29

标签: sql-server sql-server-2005

我们在SQL Server 2005 64位标准版上运行了一个非常大的表(> 77M记录和增长),我们看到了一些性能问题。每天添加的记录多达十万条。

有人知道SQL Server标准版可以处理的记录数量是否有限制?应该考虑转向企业版还是我们可以使用一些技巧?

其他信息:

有问题的表非常扁平(14列),有一个聚集索引,包含6个字段,另外两个索引在单个字段上。

我们使用3个字段添加了第四个索引,这些字段位于一个问题查询中的select中,并且没有看到估计性能的任何差异(查询是必须在非工作时间运行的流程的一部分所以我们不要还有指标)。这些字段是聚集索引的一部分。

10 个答案:

答案 0 :(得分:9)

同意上面的Marc和Unkown ...聚集索引中的6个索引太多了,特别是在只有14列的表上。您不应该有超过3或4,如果是,我会说1或2。您可能知道聚集索引是磁盘上的实际表,因此当插入记录时,数据库引擎必须对它进行排序将它放在磁盘上有序排列的位置。非聚集索引不支持,它们支持查找“表”。根据以下第一点,我的VLDB布局在磁盘上(CLUSTERED INDEX)。

  1. 将聚簇索引减少到1或2.最佳字段选择是IDENTITY(INT),如果您有一个,或者将字段添加到数据库的日期字段,或者其他一些字段是自然排序数据如何添加到数据库中。重点是你试图将数据保存在表格的底部......或者以最佳(90%以上)的方式将其放在磁盘上,以便读出记录。这使得它不会进行任何重组,或者只需要一次点击即可将数据放在正确的位置以获得最佳读数。确保将删除的字段放入非聚集索引中,这样您就不会失去查找功能。我从来没有在我的VLDB上放置超过4个字段。如果您有频繁更新的字段,并且它们包含在您的聚簇索引OUCH中,那将会重新组织磁盘上的记录并导致COSTLY碎片。
  2. 检查索引上的fillfactor。填充因子数(100)越大,数据页和索引页将越多。关于您拥有的记录数和插入的记录数,您将更改非聚集索引的fillfactor#(+或 - ),以便在插入记录时允许填充空间。如果将聚簇索引更改为顺序数据字段,那么在聚簇索引上这将无关紧要。经验法则(IMO),60-70 fillfactor用于高写入,70-90用于中等写入,90-100用于高读取/低写入。通过将fillfactor降为70,意味着对于页面中的每100条记录,将写入70条记录,这将为新的或重组的记录留下30条记录的可用空间。吃掉更多的空间,但它确实每晚都要去DEFRAG(见下面的4)
  3. 确保表格中存在统计信息。如果要使用“sp_createstats'indexonly'”扫描数据库以创建统计信息,则SQL Server将创建引擎已累积的所有索引的所有统计信息,这些索引需要统计信息。不要忽略'indexonly'属性,否则你将为每个字段添加统计数据,这样就不会好了。
  4. 使用DBCC SHOWCONTIG检查表/索引,以查看哪些索引最多碎片化。我不会在这里详细介绍,只要知道你需要这样做。然后根据该信息,相对于索引发生变化的变化以及变化速度(随时间变化)向上或向下更改fillfactor。
  5. 设置将在各个索引上联机(DBCC INDEXDEFRAG)或脱机(DBCC DBREINDEX)的作业计划以对其进行碎片整理。警告:如果没有维护时间,请不要在这个大型表上执行DBCC DBREINDEX,因为它会导致应用程序关闭...尤其是在CLUSTERED INDEX上。你被警告过了。测试和测试这部分。
  6. 使用执行计划查看SCANS和FAT PIPES存在的内容并调整索引,然后进行碎片整理并重写存储过程以消除这些热点。如果在执行计划中看到RED对象,那是因为该字段没有统计信息。那很糟。这一步更多的是“艺术而不是科学”。
  7. 在非高峰时段,使用FULLSCAN运行UPDATE STATISTICS,为查询引擎提供尽可能多的有关数据分布的信息。否则,在工作日期间对表格执行标准的更新统计(标准10%扫描),或者更经常地根据您的观察情况进行操作,以确保引擎有更多关于数据分布的信息,以便有效地检索数据。
  8. 对不起,这太长了,但这非常重要。我只给你这里最少的信息,但会帮助你。对于需要时间和测试的这些要点所使用的策略,存在一些直觉和观察结果。

    无需进入企业版。我这样做是为了通过分区获得之前所说的功能。但我特别喜欢在搜索和在线DEFRAGING和维护方面拥有更好的多线程功能......在企业版中,它与VLDB相比要好得多,也更友好。标准版也不处理与在线数据库一起使用DBCC INDEXDEFRAG。

答案 1 :(得分:7)

我要看的第一件事是索引。如果在Management Studio中使用执行计划生成器,则需要查看索引查找或聚簇索引查找。如果您看到扫描,特别是表扫描,则应该查看对通常搜索的列进行索引,以查看是否可以提高性能。

您当然不需要转移到企业版。

答案 2 :(得分:5)

您真的需要在一张桌子中访问所有7700万条记录吗?

例如,如果您只需要访问最近X个月的数据,那么您可以考虑创建归档策略。这可用于将数据重定位到存档表,以减少数据量,随后在“热”表上查询时间。

这种方法可以在标准版中实施。

如果您升级到企业版,则可以使用表分区。同样,根据您的数据结构,这可以显着提高性能。分区也可用于实现前面提到的策略,但管理开销较少。

这是一篇关于SQL Server 2005中表分区的优秀白皮书

http://msdn.microsoft.com/en-us/library/ms345146.aspx

我希望我所详述的内容清晰易懂。如果您需要进一步的帮助,请直接与我联系。

干杯,

答案 3 :(得分:5)

  

[有一个包含6个字段的聚簇索引,以及单个字段上的另外两个索引。]

在不知道有关字段的任何细节的情况下,我会尝试找到一种方法来缩小聚簇索引。

使用SQL Server,所有聚簇键字段也将包含在所有非聚集索引中(作为从非聚集索引到实际数据页面进行最终查找的一种方式)。

如果你有6个字段,每个字节8个字节= 48个字节,再加上两个索引乘以7700万行 - 你会看到很多浪费的空间转化为很多 I / O操作(从而降低性能)。

对于聚集索引,它绝对是唯一的,它是唯一的,稳定的,并且尽可能小(最好是单个INT等)。

马克

答案 4 :(得分:4)

http://msdn.microsoft.com/en-us/library/ms143432.aspx

你有一些成长的空间。

就性能问题而言,这是另一个问题。缓存,分片,规范化,索引,查询调优,应用程序代码调整等。

答案 5 :(得分:1)

标准应该能够处理它。我会查看索引和您使用表的查询。您希望以这样的方式构造事物,使得插入不会导致过多的索引重新计算,但您的查询仍然可以利用索引将查找限制为表的一小部分。

除此之外,您可以考虑对表进行分区。这将允许您将表分成几个逻辑组。你可以“幕后”,所以它仍然作为一个表出现在sql server中,即使它是单独存储的,或者你可以手动完成(创建一个新的'archive'或year table并手动移动行) 。无论哪种方式,只有之后才先查看其他选项,因为如果你没有做到这一点,你仍然必须检查每个分区。另外:分区 require Enterprise Edition,这是另一个保存最后手段的原因。

答案 6 :(得分:1)

就其本身而言,77M记录对于SQL Server来说并不是很多。你是如何加载100,000条记录的?那是每天批量加载吗?或通过某种OLTP应用程序?是你遇到的性能问题,即添加数据?或者是提供最多问题的查询?

如果您一次添加100K记录,并且添加的记录正在强制群集索引重新组织您的表,那么这将很快导致您的性能下降。有关表结构,索引和插入数据类型的更多详细信息将有所帮助。

此外,ram的数量和磁盘的速度会产生很大的不同,你在运行什么?

答案 7 :(得分:1)

也许这些是小痣,但...... (1)关系数据库没有FIELDS ......他们有COLUMNS。 (2)IDENTITY列通常意味着数据未规范化(或设计者是懒惰的)。列的某些组合必须是唯一的(并且这些列构成主键) (3)对datetime列进行索引通常是个坏主意;对datetime列进行聚类通常也是一个坏主意,尤其是不断增加的datetime列,因为所有插入都争用磁盘上的相同物理空间。在只读表中对日期时间列进行聚类,其中该列是范围限制的一部分,这通常是一个好主意(看看这些想法是如何冲突的?谁说数据库设计不是艺术?!)

答案 8 :(得分:0)

您有哪种类型的磁盘?

您可能会监视某些磁盘计数器以查看请求是否在排队。

您可以将此表放入另一个驱动器中,将其移动到另一个驱动器中。您也可以使用索引。

答案 9 :(得分:0)

最初我想同意马克。聚集索引的宽度似乎很可疑,因为它基本上将用作对所有记录执行查找的键。聚集索引越宽,访问速度越慢。并且六个字段聚集索引真的非常可疑。

聚簇索引不需要唯一性。实际上,应该在聚簇索引中的字段的最佳候选者是非唯一的并且在连接中使用的字段。例如,在Persons表格中,每个Person属于一个Group,您经常加入PersonsGroups,同时按群组访问批量的人,对于这个特定的用例,Person.group_id将是理想的候选者。