【问题标题】:Database design: one huge table or separate tables?数据库设计:一张大表还是单独的表?
【发布时间】:2011-02-15 12:25:11
【问题描述】:

目前我正在设计一个用于我们公司的数据库。我们使用的是 SQL Server 2008。该数据库将保存从多个客户那里收集的数据。该数据库的目标是获取多个客户的总体基准数据。

最近,我特别担心一张桌子会变得非常大。每个客户大约有 20.000.000 行数据,数据库中很快就会有 30 个客户(如果不是更多的话)。将在此表上进行大量查询。我已经注意到性能问题和用户被暂时锁定。

我的问题是,我们将来是否能够处理这张桌子,还是将这张桌子拆分为每个客户的小桌子更好?


更新:距离我们第一次创建表格已经过去了大约半年。按照下面的建议,我创建了一些巨大的表格。从那时起,我一直是experimenting with indexes,并决定在前两列(医院代码和部门代码)上建立一个聚集索引,如果我们有企业版,我们会在上面对表进行分区。正如 Galwegian 预测的那样,这种设置直到最近都运行良好,性能问题正在涌现。重建索引需要很长时间,用户相互锁定,查询通常比他们应该花费的时间更长,对于大多数查询,首先将数据的相关部分复制到临时表中,在临时表上创建索引并运行询问。这不是应该的样子。因此,我们正在考虑购买企业版以使用分区表。如果购买无法通过我计划使用workaround to accomplish partitioning in Standard Edition

【问题讨论】:

  • 对于您的锁,您是否在 SELECT 语句中指定 NOLOCK 查询提示?
  • 还没有,但现在我会的。谢谢。
  • 再想一想,我可能不会,考虑到我在这个主题上找到的一些信息,以及下面的讨论。
  • 表分区会有所帮助。此外,重建索引不会花费太多时间,因为现在索引将特定于每个分区

标签: sql-server sql-server-2008 database-design data-warehouse


【解决方案1】:

从一张大表开始,然后在适当的情况下应用 2008 年的表分区功能,如果性能成为问题

【讨论】:

  • 如果我必须给某人点数......这个答案很简洁,表分区提示让我找到了很多我可以使用的特定 SQL Server 2008 信息。所以感谢 Galwegian,以及所有在场的人!
【解决方案2】:

数据仓库应该很大(线索就在名称中)。按仓储标准,2000 万行大约是中等的,尽管 6 亿行可以被认为是大的。

要记住的是,这么大的桌子有不同的物理特性,就像黑洞一样。因此,调整它们需要一组不同的技术。另一件事是,数据仓库的用户必须了解他们正在处理大量数据,因此他们不能期望每个查询的响应都在亚秒级(或者实际上是亚分钟级)。

分区可能很有用,尤其是当您有明确的分界线时,例如在您的案例中,客户。您必须意识到,分区会降低查询的性能,这些查询跨越了分区键的粒度。所以它不是灵丹妙药。

【讨论】:

  • 黑洞是什么意思?
  • @StockB:他的意思是大型数据库与普通数据库完全不同,就像黑洞(在天体物理学中)与普通物体完全不同。它们是如此不同,以至于我们在处理它们时习惯的“通常”规则根本不适用。他们有自己的一套规则和假设,您必须遵守。
【解决方案3】:

出于性能原因的拆分表称为分片。此外,数据库模式可以或多或少标准化。规范化的模式具有单独的表以及它们之间的关系,并且数据不会重复。

【讨论】:

  • 我的命名法关闭了吗?我称拆分表分区。我将分片称为出于特定目的对数据集进行物理或分离,不是吗?
【解决方案4】:

我假设您的数据库已正确规范化。在 SQL Server 中处理您在单个表上引用的数据量应该不是问题;我认为您需要做的是检查您的索引。

【讨论】:

  • 我已经规范化了我的数据,但是我所指的表是完全非规范化的,因为它会被查询很多并且不会经常改变。
  • 如果您不更新表格,那么我想知道您为什么要锁定用户。
  • 可能是因为我们仍处于设计阶段,我们经常将数据批量加载到数据库中。但我明白你的意思,锁定问题将在生产情况下消失。谢谢!
【解决方案5】:

由于您也将您的问题标记为“数据仓库”,因此我假设您对该主题有所了解。根据您的目标,您可以选择星型模式(具有事实和维度表的多维模型)。将所有快速变化的数据存储在 1 个表中(每个主题),将慢速变化的数据存储在另一个维度/“雪花”表中。

另一个选项是 Dan Lindstedt 的 DataVault 方法。这有点复杂,但为您提供了充分的灵活性。

http://danlinstedt.com/category/datavault/

【讨论】:

  • 呵呵.. 我希望我对数据仓库有更多的了解。你不是在找工作,是吗:)
【解决方案6】:

在设计合理的数据库中,记录的数量并不多,SQl 服务器应该可以轻松处理。

分区的单个表通常是最好的方法。尝试维护单独的个人客户表在时间和精力方面非常昂贵,并且更容易出错。

如果您遇到性能问题,还要检查您当前的查询。如果您没有正确的索引(例如,您是否索引了外键字段?)查询会很慢,如果您没有 sargeable 查询,如果您使用相关子查询或游标,它们会很慢,它们会很慢。您返回的数据是否超出了严格要求?如果您在生产代码中的任何位置选择 *,请摆脱它并仅返回您需要的字段。如果您使用调用视图的视图调用视图,或者如果您使用 EAV 表,您将在此级别遇到性能问题。如果您允许框架自动生成 SQl 代码,您的查询可能会很糟糕。请记住 Profiler 是您的朋友。当然你也可能有硬件问题,你需要一个相当大的专用服务器来处理这么多的记录。在您的网络服务器或小盒子上运行它是行不通的。

我建议您需要聘请具有性能调优经验的专业 dba。这是相当复杂的东西。应用程序程序员设计的数据库在获得真实数量的用户和记录时通常表现不佳。数据库的设计必须考虑到数据完整性、性能和安全性。如果你不这样做,拥有它们的变化确实很小。

【讨论】:

  • 我没有使用框架,我使用的是索引,而且我们确实有一个 kickass 服务器。但是,我确实是该主题的新手,我们正在寻找专业的 DBA 加入团队。我还没有使用 Profiler,所以感谢您的提示。
【解决方案7】:

分区肯定是需要研究的。我有一个分片了 2 个表的数据库。每个表包含大约 30-3500 万条记录。我已经将它合并到一个大表中并分配了一些好的索引。到目前为止,我还没有必要对这张表进行分区,因为它正在工作,但我一直牢记分区。与数据分片时相比,我注意到的一件事就是数据导入。现在速度变慢了,但我可以忍受,因为可以重写导入工具;o)

【讨论】:

    【解决方案8】:

    一张表,使用表分区。

    根据所提供的信息,我认为使用 NOLOCK 的建议是不合理的。 NOLOCK 意味着您将从查询(脏读和幻读)中获得不准确和不可靠的结果。在使用 NOLOCK 之前,您需要确保这不会对您的客户造成问题。

    【讨论】:

    • Dirty Reads Yes - 它不会影响 Phantoms,因为这些也会在默认隔离级别下发生。
    【解决方案9】:

    这是一张单人平桌吗(没有特定型号)?通常在数据仓库中,您要么有一个规范化的数据模型(至少是第三范式 - 通常在实体关系模型中),要么有维度数据(Kimball 方法或变体 - 通常是事实表和一组关联的维度表)星)。

    在这两种情况下,索引都起着很大的作用,分区也可以在非常大的数据集上执行查询(但分区通常不是关于性能,而是关于维护能够快速添加和删除分区) - 但这实际上取决于聚合的顺序和查询的类型。

    【讨论】:

      【解决方案10】:

      一张桌子,然后担心性能。也就是说,假设您正在为每个客户收集完全相同的信息。这样,如果您必须添加/删除/修改一列,您只需在一个地方进行。

      【讨论】:

        【解决方案11】:

        如果您在 MS SQL 服务器上并且想要保留单个表,则表分区可能是一种解决方案。

        【讨论】:

          【解决方案12】:

          保留一张表 - 2000 万行并不大,而且客户也不是那种可以轻松“归档”的表,而且搜索多个表以查找客户的繁琐工作是不值得的(SQL 在 BTree 搜索方面可能比您自己发明的效率更高)

          但是,您需要查看性能和锁定问题 - 这将阻止您的数据库扩展。

          【讨论】:

            【解决方案13】:

            如果有常见查询,您还可以创建补充表来保存已计算的历史信息详细信息。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-03-14
              • 1970-01-01
              • 2014-01-31
              • 2010-11-08
              • 1970-01-01
              相关资源
              最近更新 更多