【问题标题】:Handling 100's of 1,000,000's of rows in T-SQL2005在 T-SQL2005 中处理 1,000,000 行中的 100 行
【发布时间】:2011-03-18 22:00:15
【问题描述】:

我有几个数据库,其中包含需要导入新格式架构的简单数据。我想出了一个灵活的模式,但它依赖于旧数据库的关键数据存储在一个表中。该表只有一个主键、一个外键(都是 int 的)、一个日期时间和一个小数字段,但是将两个旧数据库的行数相加表明,这个新表的总行数约为 200,000,000 行。

我该如何处理这么多的数据?这是可以追溯到大约 10 年前的数据,并且确实需要可用。幸运的是,我们将来查询时甚至不需要提取其中的 1%,但它确实需要可访问。

我的想法是基于每年拥有多个表、(源数据的)供应商等 - 甚至每年拥有一个数据库,最近 2 年在一个数据库中(其中还包含存储的procs 来管理这一切。)

非常、深刻、非常感谢任何和所有帮助、想法、建议,

马特。

【问题讨论】:

  • 您使用的是哪个版本?例如,企业中有比标准更多的分区选项。
  • 我相信是SQL Server标准版。

标签: sql-server-2005 tsql large-data-volumes


【解决方案1】:

最重要的是。考虑分析您的查询并测量您的实际瓶颈在哪里(尝试识别missing indexes),您可能会发现您可以将所有内容存储在一个表中,或者购买一些额外的硬盘足以获得足够的性能。

现在,对于建议,您是否考虑过分区?您可以按时间范围创建分区,或者一个分区包含 1% 的常用数据,另一个分区包含 99% 的数据。

这大致相当于按年份或供应商之类的手动拆分表,但由服务器内部处理。

另一方面,将表实际拆分为“当前”和“历史”可能更有意义。

另一个可能的大小改进是使用 int(如 epoch)而不是 datetime,并提供从 datetime 转换为 int 的函数,因此具有类似的查询

SELECT * FROM megaTable WHERE datetime > dateTimeToEpoch('2010-01-23')

如果您需要执行复杂的日期时间查询,这种大小节省可能会带来成本效益。 Although on cubes there is the standard technique of storing, instead of an epoch, an int in YYYYMMDD format.

【讨论】:

  • 您是否有任何经验或数字表明存储整数和转换比日期时间更有效?如果秒数不重要,您是否考虑过 smalldatetime?
  • 在我的用例中,秒很重要,int 是 datetime 类型大小的一半。我还没有测量性能。我只是希望它会更快,仅仅是因为要移动的数据更少。我还希望它对于简单的比较(日期时间>'日期')非常有效,如果您必须在更复杂的条件下查询很多,例如一天中的小时,那么您可能会为节省的空间付出代价(如您必须在每一行上调用转换函数)
  • 我不会假设我是你。我看不出为什么大于比较的 int 会比日期时间比较快。特别是如果您的查询有一个索引,那么即使有数百万行,它仍然只会进行少量比较。至于大小,smalldatetime 和 int 大小一样。
  • @tster:正如我所说,我实际上是为了空间。而且,尽管我看到了它可能更快的原因,但您是正确的,a)它可能已被优化掉,b)我需要证明它。我会编辑以反映它。
【解决方案2】:

对于这么小的元组大小(2 个整数、1 个日期时间、1 个十进制),我认为拥有一个包含所有结果的表会很好。 SQL server 2005 不限制表中的行数。

如果您在这条路上遇到性能问题,那么是时候寻找替代方案了。在那之前,我会奋力前行。

编辑:假设您使用 DECIMAL(9) 或更小,您的总元组大小为 21 个字节,这意味着您可以将整个表存储在不到 4 GB 的内存中。如果您有一个不错的服务器(8+ GB 内存)并且这是主要内存用户,那么表和二级索引可以存储在内存中。这应该确保在填充缓存之前的较慢预热时间后超快速查询。

【讨论】:

    【解决方案3】:

    将这些数据存储在一个表中有什么问题?像 Microsoft SQL 2005 这样的企业级 SQL 服务器可以轻松处理它。

    顺便说一句,不要每年做表、每个供应商的表或其他类似的事情。如果您必须存储类似的项目集,则需要一个且只有一个表。设置多个表来存储相同类型的东西会导致问题,比如:

    • 查询将非常难以编写,如果您必须从多个表中查询,性能将会下降。

    • 数据库设计将非常难以理解(尤其是因为将相同类型的项目存储在不同的地方并不是一件自然的事情)。

    • 您将无法轻松修改您的数据库(在您的情况下这可能不是问题),因为您必须更改每个表,而不是更改一个表。

    • 这需要自动化一堆任务。让我们看看你每年有一张桌子。如果在 2011-01-01 00:00:00.001 插入新记录,是否会创建新表?如果您必须创建一个新表,您会在每次插入时检查吗?它将如何影响性能?你能轻松测试一下吗?

    如果“最近”和“旧”数据之间存在真实、可见的分离(例如,您必须每天使用仅上个月保存的数据,并且您必须保留所有旧数据,但不要使用它),你可以用两台 SQL 服务器(安装在不同的机器上)构建一个系统。第一个高度可用的服务器将用于处理最近的数据。第二个,较少可用且针对写入进行了优化,将存储其他所有内容。然后,按计划,程序会将旧数据从第一个移动到第二个。

    【讨论】:

    • 我接受企业版应该很容易做到这一点。当您说“没有太多痛苦”时,您的意思是它会做到这一点还是我必须考虑某些配置?
    • 我同意由于@tster 给出的原因可能不需要分区,但您反对它的论点假设他将推出自己的分区方案。 SQL Server 内置了对分区的支持。在企业版中更是如此。尽管在其他版本中提供了分区视图。
    • @Matt W:这取决于上下文。恕我直言,2×10⁸ 行并不大(参见 tster 的回复,更详细)。因此,假设您有一台好的服务器并且您不必每秒进行数万次查询,我认为您不需要更改配置。您始终可以用随机数据填充数据库并对其进行测试以查看真实结果。
    • @Martin Smith:我很抱歉,也许我的回答不够明确,但我从不鼓励创建他自己的分区方案。当我写下我的答案时,对我来说只有两种解决方案:仅使用一张表,以及在两台不同的机器上使用两台不同的服务器(也能够优化硬件)。现在,由服务器内部处理的 SQL 分区方案是另一种处理方式,而且是一种很好的方式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-23
    • 2011-12-01
    • 1970-01-01
    • 2012-09-09
    • 2020-07-14
    • 1970-01-01
    • 2021-09-29
    相关资源
    最近更新 更多