SQL Server:表中的最大行数


80

我开发了将大量数据存储在其数据库表之一(SQL Server版本8、9或10)中的软件。假设每天大约有100,000条记录插入到该表中。每年大约有3600万条记录。为了避免性能下降,我决定每天创建一个新表(名称中带有当前日期的表)以减少每个表的记录数。

你能告诉我,这是个好主意吗?SQL Server表是否有记录限制?还是您知道在性能大幅降低之前,一个表中可以存储多少条记录(或多或少)?


33
“程序员浪费大量时间来思考或担心程序非关键部分的速度,而在考虑调试和维护时,这些对效率的尝试实际上会产生严重的负面影响。我们应该忘记效率低下, 97%的时间:过早的优化是万恶之源,但我们不应该在这3%的临界风险中放弃机会。” 1974
马修·洛克

Answers:


36

对此很难给出一个通用的答案。它实际上取决于许多因素:

  • 您的行是多少
  • 您存储什么样的数据(字符串,斑点,数字)
  • 您如何处理数据(只需将其保存为存档,并定期查询)
  • 你的桌子上有索引吗?
  • 您的服务器规格是什么

等等

就像在这里其他地方回答的那样,每天10万张,因此每张桌子是过大的-我建议每月或每周甚至每季度一次。您拥有的表越多,维护/查询的噩梦就越大。


13
我想加强“更大的维护/查询梦night”-从个人经验来看,我避免像瘟疫一样分裂成桌子。
Daniel James Bryars

92

这些是SQL Server 2008 R2的一些最大容量规格

  • 数据库大小:524,272 TB
  • 每个SQL Server实例的数据库:32,767
  • 每个数据库的文件组:32,767
  • 每个数据库的文件数:32,767
  • 文件大小(数据):16 TB
  • 文件大小(日志):2 TB
  • 每表行:受可用存储空间限制
  • 每个数据库的表:数据库中对象数的限制

22
我怀疑如果您的行数超过9,223,372,036,854,775,807,您会遇到问题(最大大小为a bigint
Martin Smith

11
您是否曾经计算过OP提到的每天100000行所需的年数?
Erwin Smout 2011年

75
懒惰的发布时间:252,695,124年。
NotMe 2012年

18
@NotMe不能复活和挑剔,但我有252695124297年。(有时我希望我属于您提到的懒惰人群)
philthyfool

4
@philthyfool Le年的一天有很大的不同。我得到252,522,163,911。而且,这些是我一生中最美好的时光,我现在无法回头。
Suamere

53

我在SQL Server 2008 R2中有一个三列表,其中有60亿行以上。

我们每天都在查询它,以为我们的客户创建每分钟的系统分析图表。我还没有注意到任何数据库性能方面的问题(尽管它每天增长〜1 GB的事实确实使管理备份比我想要的要复杂得多)。

2016年7月更新

行数

在备份变得足够大以至于我们决定截断两年以上的记录(大约700 GB存储在多个备份中,包括昂贵的磁带上)之前,我们达到了约245亿行。值得注意的是,性能并不是此决定的主要推动力(即,效果仍然很好)。

对于发现自己试图从SQL Server删除200亿行的任何人,我强烈建议您阅读本文。链接消失时的相关代码(请阅读文章以获取完整说明):

ALTER DATABASE DeleteRecord SET RECOVERY SIMPLE;
GO

BEGIN TRY
    BEGIN TRANSACTION
        -- Bulk logged 
        SELECT  *
        INTO    dbo.bigtable_intermediate
        FROM    dbo.bigtable
        WHERE   Id % 2 = 0;

        -- minimal logged because DDL-Operation 
        TRUNCATE TABLE dbo.bigtable;  

        -- Bulk logged because target table is exclusivly locked! 
        SET IDENTITY_INSERT dbo.bigTable ON;
        INSERT INTO dbo.bigtable WITH (TABLOCK) (Id, c1, c2, c3)
        SELECT Id, c1, c2, c3 FROM dbo.bigtable_intermediate ORDER BY Id;
        SET IDENTITY_INSERT dbo.bigtable OFF;
    COMMIT
END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0
        ROLLBACK
END CATCH

ALTER DATABASE DeleteRecord SET RECOVERY FULL;
GO

2016年11月更新

如果您打算将大量数据存储在单个表中,请不要。我强烈建议您考虑对表进行分区(手动或内置功能(如果您正在运行企业版)。这使得丢弃旧数据就像每周(每月/每月/一次)一次删除表一样容易。如果您没有Enterprise(我们没有),则只需编写一个脚本,该脚本每月运行一次,删除2年以上的表,创建下个月的表,并重新生成连接所有分区的动态视图。表格一起查询。显然,您应该根据用例的合理性来定义“每月一次”和“大于2年”。


14
高达105亿,仍在不断攀升。只是不要尝试执行COUNT()。;)
Dan Bechard 2015年

6
已经一年了,我们有165亿行。我们只是添加了一个额外的数据源,所以现在它的增长速度更快。我们还将该数据库移到了自己的SQL实例中,从而使我们可以专用内存而不会耗尽服务器上的其他数据库。我仍然能够在不到一秒钟的时间内绘制过去三年中任何24小时内的任何数据点。我们的分析师喜欢它。
Dan Bechard

我知道已经有一段时间了,但是您能告诉我您在运行该数据库的哪种硬件吗?很好奇,因为我们有5个十亿行的表,每年增长1十亿,和IK想看看这个开始变得在未来的问题
Jeroen1984

3
@ Jeroen1984这是一台虚拟机,运行在具有两个Intel Xeon CPU E5-2430处理器的Hyper-V主机ProLiant DL360e Gen8上。VM具有38GB的静态分配的RAM,以及一些我不记得的虚拟处理器。
Dan Bechard

19

我不知道行数限制,但是我知道有超过1.7亿行的表。您可以使用分区表(2005+)或连接多个表的视图来加快速度。


19

我不特别了解MSSQL,但是对于企业数据库而言,3600万行并不算大-使用大型机数据库,100,000行对我来说就像是配置表:-)。

尽管我不是Microsoft某些软件的忠实拥护者,我们这里不是在讨论Access:我认为他们可以使用其企业DBMS处理相当大的数据库大小。

我怀疑,如果确实需要拆分,那么日子可能太好了,无法拆分。


5

我们在SQL Server 2005和2008中有超过10亿行的表格(每天增加3000万行)。我简直无法想象每天都会把老鼠拆成一张新桌子。

添加适当的磁盘空间(无论如何还是需要)和RAM便宜得多。


4

这要看情况,但是我想说,为了简单起见,最好将所有内容都放在一个表中。

每天100,000行实际上并不是很大的数目。(取决于您的服务器硬件)。我亲自看到MSSQL在单个表中最多可以处理100M行,没有任何问题。只要使索引保持顺序,就应该很好。关键是要有大量的内存,以便不必将索引换出到磁盘上。

另一方面,这取决于您如何使用数据,如果您需要进行大量查询,并且需要跨越数天的不太可能的数据(因此您无需联接表),则需要更快地将其分离到多个表中。这通常用于工业过程控制之类的应用中,您可能每10秒读取50,000个仪器的值。在这种情况下,速度非常重要,但简单性却不重要。


3

我们一次在表上溢出了一个整数主键(约24亿行)。如果存在行数限制,则您不可能每年仅达到3600万行。


2

您可以填充表,直到您有足够的磁盘空间。为了获得更好的性能,您可以尝试迁移到SQL Server 2005,然后对表进行分区,然后将各个部分放在不同的磁盘上(如果您具有可以真正帮助您的RAID配置)。仅在企业版SQL Server 2005中才可以进行分区。您可以在以下链接中查看分区示例:http : //technet.microsoft.com/zh-cn/magazine/cc162478.aspx

您也可以尝试为最常用的数据部分创建视图,这也是解决方案之一。

希望这可以帮助...


0

我在Windows2003的SQL Server 8上遇到的最大表是7.99亿,有5列。但是,要根据SLA和使用情况来衡量它是否良好,例如,加载50-100,000,000条记录,并查看它是否仍然有效。


2
不确定这是否真的是答案。
Andrew Barber 2012年

-1
SELECT Top 1 sysobjects.[name], max(sysindexes.[rows]) AS TableRows, 
  CAST( 
    CASE max(sysindexes.[rows]) 
      WHEN 0 THEN -0 
      ELSE LOG10(max(sysindexes.[rows])) 
    END 
    AS NUMERIC(5,2)) 
  AS L10_TableRows 
FROM sysindexes INNER JOIN sysobjects ON sysindexes.[id] = sysobjects.[id] 
WHERE sysobjects.xtype = 'U' 
GROUP BY sysobjects.[name] 
ORDER BY max(rows) DESC

我跑了这个查询,并得到了这个结果。我的数据库中有UrlCategories表。那么,这个结果意味着什么呢?名称TableRows L10_TableRows Url类别7 0.85
Aditya Bokade 2013年

-4

每月对表进行分区。这是处理每天大量涌入的表的最佳方法,无论是oracle还是MSSQL。


4
不确定这是对所问特定问题的答案。
Andrew Barber
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.