【问题标题】:SQL Server: the maximum number of rows in table [closed]SQL Server:表中的最大行数[关闭]
【发布时间】:2010-10-20 01:02:32
【问题描述】:

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

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

【问题讨论】:

  • "程序员浪费大量时间去思考或担心他们程序中非关键部分的速度,而在考虑调试和维护时,这些效率上的尝试实际上产生了强烈的负面影响。我们应该忘记小的效率,比如说大约 97% 的时间:过早的优化是万恶之源。但我们不应该放弃关键的 3% 的机会。克努特 1974 年
  • 真实的话,错误的地方。程序的一部分是否“关键”的一个指标是,它的执行是否会显着影响我的应用程序的性能。因此,虽然开发人员大部分时间都在担心错误的事情(我不知道)这可能是真的,但这里的这件事绝对不是那些错误的事情之一。

标签: sql-server database-design


【解决方案1】:

这些是Maximum Capacity Specifications for SQL Server 2008 R2中的一些

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

【讨论】:

  • 我怀疑如果您的行数超过 9,223,372,036,854,775,807 行,您会遇到问题(bigint 的最大大小)
  • 您是否计算过 OP 提到的 100000 行/天达到该行数所需的年数?
  • 为懒人发帖:252,695,124 年。
  • @NotMe 不要复活和吹毛求疵,但我有 252695124297 年。 (有时我希望我是你提到的懒惰人群)
  • @philthyfool 闰年的一天是一个巨大的差异。我得到 252,522,163,911。此外,这是我生命中非常美好的几分钟,我现在无法回头。
【解决方案2】:

我在 SQL Server 2008 R2 中有一个包含超过 60 亿行的三列表。

我们每天都会查询它,以便为我们的客户创建每分钟的系统分析图表。我没有注意到任何数据库性能下降(尽管它每天增长约 1 GB 的事实确实使管理备份比我想要的要复杂一些)。

2016 年 7 月更新

我们做到了~245 亿行,然后备份变得足够大,我们决定截断超过两年的记录(约 700 GB 存储在多个备份中,包括在昂贵的磁带上)。值得注意的是,性能并不是这个决定的重要动力(即,它仍然工作得很好)。

对于发现自己试图从 SQL Server 中删除 200 亿行的任何人,我强烈推荐 this article。链接失效时的相关代码(阅读文章以获得完整解释):

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 年”应该由您根据对您的用例有意义的内容来定义。直接从包含数百亿行数据的表中删除将 a) 花费大量时间 b) 将事务日志填满数百或数千次。

【讨论】:

  • 高达 105 亿,仍在不断增加。只是不要尝试执行 COUNT()。 ;)
  • 一年过去了,我们有 165 亿行。我们刚刚添加了一个额外的数据源,所以它现在增长得更快了。我们还将这个数据库移动到它自己的 SQL 实例中,以允许我们专用内存而不会使服务器上的其他数据库挨饿。我仍然能够在不到一秒的时间内绘制过去 3 年中任何 24 小时内的任何数据点。我们的分析师喜欢它。
  • 我知道这已经有一段时间了,但是您能告诉我您在哪种硬件上运行此数据库吗?非常好奇,因为我们有一个 50 亿行的表,每年增长 10 亿行,ik 想知道这是否会在未来开始出现问题
  • @Jeroen1984 这是一个在 Hyper-V 主机 ProLiant DL360e Gen8 上运行的虚拟机,带有两个 Intel(R) Xeon(R) CPU E5-2430 处理器。 VM 有 38GB 的​​静态分配 RAM,以及一些我不记得的虚拟处理器。
【解决方案3】:

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

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

等等

正如此处其他地方所回答的那样,每天 100,000 份,因此每张桌子是多余的 - 我建议每月或每周甚至每季度一次。您拥有的表越多,维护/查询的噩梦就越大。

【讨论】:

  • 我想重新执行“更大的维护/查询噩梦” - 从个人经验来看,我会避免像瘟疫那样拆分成表格。
【解决方案4】:

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

【讨论】:

    【解决方案5】:

    我不具体了解 MSSQL,但 3600 万行对于企业数据库来说并不大 - 使用大型机数据库,100,000 行对我来说听起来像是一个配置表:-)。

    虽然我不是一些微软软件的忠实粉丝,但这不是我们在这里谈论的 Access:我假设他们可以使用他们的企业 DBMS 处理相当大的数据库大小。

    如果确实需要拆分,我怀疑天数可能太小了,无法拆分它。

    【讨论】:

      【解决方案6】:

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

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

      【讨论】:

        【解决方案7】:

        这取决于,但为了简单起见,我会说最好将所有内容都放在一个表中。

        每天 100,000 行并不是一个巨大的数字。 (取决于您的服务器硬件)。我个人见过 MSSQL 在单个表中处理多达 100M 行而没有任何问题。只要您保持索引井井有条,一切都会好起来的。关键是要有 内存,这样就不必将索引换出到磁盘。

        另一方面,这取决于您使用数据的方式,是否需要进行大量查询,并且需要跨越多天的不太可能的数据(因此您不需要加入表格)将它分成多个表会更快。这通常用于工业过程控制等应用中,您可能每 10 秒读取 50,000 台仪器的值。在这种情况下,速度非常重要,但简单性则不是。

        【讨论】:

          【解决方案8】:

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

          【讨论】:

            【解决方案9】:

            您可以填充该表,直到您有足够的磁盘空间。

            为了获得更好的性能,您可以尝试迁移到 SQL Server 2005,然后对表进行分区并将部分放在不同的磁盘上(如果您的 RAID 配置确实可以帮助您)。分区只能在 SQL Server 2005 的企业版中进行。您可以查看partitioning example at this link

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

            【讨论】:

              【解决方案10】:

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

              【讨论】:

              • 不确定这是否真的是一个答案。
              【解决方案11】:
              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 UrlCategories 7 0.85
              【解决方案12】:

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

              【讨论】:

              • 不确定这是对特定问题的回答。
              猜你喜欢
              • 1970-01-01
              • 2017-01-31
              • 2017-07-31
              • 2023-03-08
              • 2012-03-12
              • 2012-01-08
              • 2018-08-20
              • 2010-10-11
              • 2023-03-07
              相关资源
              最近更新 更多