【问题标题】:Database: Best practice - old data?数据库:最佳实践 - 旧数据?
【发布时间】:2009-12-22 07:05:23
【问题描述】:

我有一个汽车分类列表数据库。

90天后,分类listing不再有效展示(listing过期);但是,我想保留列表以供存档。

问题:从数据库设计最佳实践和查询性能的角度来看,将旧列表 A) 保留在与当前列表相同的表中是否更好或B),将过期列表移至过期表并从当前列表表中删除该列表?

换句话说,

选项A)

table_classified_listing:
car_id
expired = true | false
...

选项B)

// only current listing in this table (expired = false)
table_classified_listing:
car_id
...

// only expired listing in this table (expired = true)
expired_table_classified_listing:
car_id
...

更新

我对选项 A 的担忧是,在我的 MySQL 数据库中 - 当我运行 EXPLAIN 时,它说它使用 expired 作为索引的主键。但是,对我的查询搜索性能更重要的是它使用price 字段,因为我正在根据price > X 进行搜索。因此,我考虑选择选项 B。

【问题讨论】:

  • Timk,这里我们使用A,但我建议不要执行 is_enabled 除非该字段真的很重要,而是在数据库中记录 time_entered 并在代码中计算过期间隔或使用视图。我可以看到一个用例,人们/想要/查看超过 30 天的分类列表。

标签: database database-design rdbms


【解决方案1】:

选项 A)这样您就可以将所有数据集中在一个地方,并且可以更轻松地创建报告查询、列出用户历史条目等。任何速度问题都应该通过该列上的数据库索引来缓解。选项 B) 是 premature optimisation

【讨论】:

    【解决方案2】:

    一般建议(您必须填补空白;-)):

    • 只有在某些情况下性能才会显着(超过一百万条记录、巨大的行大小...)。

    • 您会使用“联合”还是相同的查询来查询这两个表?如果您不会使用相同的查询来查询表,那么我建议使用不同的表(随着记录数量的增长可能会获得性能提升,但主要是意义增益)。


    重复的问题是它可能会增加工作量(编写查询,测试它们......)。但所有技术(尤其是现代技术)都允许您减少或取消重复。

    例如,使用 ORM,您可以有一个映射到公共字段但没有表的抽象实体,以及映射到您的表的两个子类。没有重复的列信息。而且 ORM 也可以创建您的数据库脚本,因此您甚至没有这些(当然,您应该为生产数据库手动查看它们)。


    UPDATE在问题更新后:

    你可以创建你想要的索引,不用担心。如果您正在寻找它来查询数据的性能未过期,价格超过 X,创建一个索引 (expired, price) 就可以了 :-)

    【讨论】:

    • 我没有计划或预见到任何需要查询这两个表(仅供参考)
    • 所以,你是说 - 选择了选项 A。正确吗?
    • @Timk 所以这一点很清楚。你有任何行大小或记录数字吗?
    • @Timk 实际上我还没有在选项之间进行选择:-)。但是我在您更新后更新了我的答案...
    【解决方案3】:

    不要用B,基本就是拆分属性。

    我的做法是基本上使用两个日期列。 ValidFromDate 和 ValidToDate。

    【讨论】:

      【解决方案4】:

      按照您所描述的任何人累积列表的速度,性能下降之前需要很长时间。并且硬件和软件性能提升更快。

      在你确定你需要它之​​前不要把事情复杂化,而简单的东西是行不通的。把它放在一张桌子上。请参阅有关pessimizations 的问题 - 这是一个。

      【讨论】:

      • +1 表示您注意到硬件和软件性能通常以更快的速度提高,您可以用数据填满机器
      【解决方案5】:

      我个人会说将所有过期的移到一个单独的表中。随着数据库的增长,您将希望从“实时”记录中获得更好的性能,因为这些记录可能最常受到打击。

      所有旧记录都会导致表大小不断增长,这意味着查询速度变慢,即使进行了查询优化等。

      编辑: 正如其他人提到的那样,这种方法的一大缺点是,如果您计划频繁地组合实时数据和存档数据。如果您总是单独引用它们,那就太好了,但如果不是,您将需要大量的连接和联合来将数据拉到一起 - 这并不理想。

      【讨论】:

      • 列区分过期/有效记录索引的性能损失如何?那不应该很快吗?
      【解决方案6】:

      对于保留旧数据的一般问题,至少还有两个附加选项:

      • 按日期对数据进行分区,然后滚动日期或分离分区。或者,将每个分区实现为单独的表,然后使用 union-all 视图将它们连接起来。在后一种情况下,您通常最好使用粗粒度分区(月而不是日)。 MySQL 应该能够支持这两种解决方案,并且分区具有提高查询性能的额外优势,与查询大部分表数据相关。
      • 导出所有要保留的数据,截断表,然后重新加载。说真的 - 当您删除大量数据时,重新加载可能比删除快得多。许多数据库没有足够的数据来执行此操作 - 至少几年内没有,然后他们的管理员发现他们需要硬件升级或清除一整年的数据。在这一点上,这种策略通常是最好的。

      回到您提供的两个解决方案:

      • 将数据保存在同一个表中。对于您的数据量,这可能是最好的方法。但是 - 在某些时候你可能仍然想放弃它(7 年?),那时你可以有一个小的异步作业来进行涓流删除,可以删除分区或可以导出/重新加载。
      • 将存档数据保存在不同的表中。如果您可以为访问频率较低的存档数据利用不同的(较少的)硬件,这将变得最有用,例如单独的服务器、较少数量的 CPU、一组不同的更便宜/慢速的磁盘、更小的内存缓冲区等。 MySQL没有足够的可配置性来做这些。另一个原因是,如果您的查询经常进行表扫描,并且如果通过将大部分数据移出可以显着提高性能。情况可能就是这样。您正在使用 MySQL - 它有一个众所周知的不成熟的优化器/规划器,并且您没有使用分区。因此,每当无法使用索引时,您都将进行表扫描。如果您需要闪电般快速的查询、小型服务器或大量行,那么我会将旧数据保存在单独的表中。但这里有一个可能更好的方法:
      • 将数据保存在两个表中,但第一个表包含 100% 的数据(新旧数据),第二个表仅包含最新数据。采用这种方法的原因是您可能想要生成各种子集或聚合 - 现在具有最新数据的表只是众多表中的一个。这些子集/聚合并不是完全必要的——你总是可以只查询你的主表。然而,分析查询往往对数据库造成相当大的冲击——这些表可以使它们变得非常快。坦率地说,任何值得花时间研究的过程都值得分析。

      【讨论】:

        【解决方案7】:

        这是我的理解:

        • 由于这些是分类列表, 数据本质上是“短暂的”, 并过期。
        • 因此,过期数据量可能会超过 “当前”或未过期的数据。

        如果我对上述内容的理解正确,那么下一个问题是您的过期数据多久使用一次?它是用来做什么的?就像@ghills 指出的那样,sql-unions 可能会减慢您的速度。

        如果过期数据不需要在线,则将其归档到单独的表中可能是有意义的。特别是如果过期行数可以超过活动行数。

        如果您将它们保存在同一个表中,“where expired=false”最终可能会成为您的常伴,并且由于选择性会很低(即很多过期行),因此无法在“过期”列上建立索引你物超所值。 (Oracle 有位图索引——但这可能根本不适用于这里)。

        【讨论】:

          【解决方案8】:

          我会把它们放在一张桌子上。否则,(a)您有两个具有相同列的表。那么,任何时候您对数据进行更改时,您都必须记住对两个表进行相同的更改。迟早有人会忘记——或者得到一个表中的数据不需要在另一个表中的好主意——现在你的设计变得更加复杂。很快,您将编写完全相同的逻辑两次:一次从“当前”表中检索,另一次从“存档”表中检索。但是随后有人对一段代码进行了更改,却忘记了对另一段代码进行相同的更改。然后下一个出现的人不能确定他们是否不同,因为他们应该不同是有充分理由的,或者如果有人忘记了。等 (b) 您似乎可能会有想要同时访问这两个表格的查询,例如“告诉我过去 12 个月内要价超过 20,000 美元的所有广告”,其中一些广告可能是最新的,而其他广告存档。这些查询现在是联合或复杂的连接,而不是简单地不包括“过期为真”或“过期为假”标志。

          至于性能问题,这很简单:创建一个包含您需要包含的任何内容的多字段键。 expired + price 或 expired + modelname 似乎很可能是关键。您可能希望将已过期放在首位,因为您的大多数查询可能都需要未过期的记录,但我只是在猜测。选择值得索引的内容是一个复杂的决定,但是当多个字段上有明显的常见查询时,就去做吧。

          【讨论】:

            【解决方案9】:

            没有通用的最佳实践。但是,如果表格变得很大并且您的搜索花费了太多时间,那么您可能需要将项目存档在单独的表格中或 soo.. 否则,您可以实施适当的索引也使事情变得更快。这实际上取决于您正在考虑的数据量和类型。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-09-16
              • 2014-08-01
              • 2010-11-06
              • 2018-11-19
              • 1970-01-01
              • 1970-01-01
              • 2015-09-10
              • 2012-05-16
              相关资源
              最近更新 更多