数据库:最佳实践 - 旧数据?

时间:2009-12-22 07:05:23

标签: database database-design rdbms

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

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

问题:从数据库设计最佳实践角度以及查询效果来看,最好将旧列表 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.

9 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:4)

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

  • 性能只会在某些情况下显着(超过一百万条记录,行数大......)。

  • 您会使用“联盟”或相同的查询查询两个表吗?如果您不使用相同的查询查询表格,那么我建议使用不同的表格(随着记录数量的增长可能会增加性能,但主要是含义增益)。


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

  

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


问题更新后

更新

您可以创建所需的索引,不用担心。如果您正在寻找它以查询超过X的价格未过期的数据,请创建一个索引(已过期,价格),您就可以了: - )

答案 2 :(得分:3)

不要使用B,它基本上是拆分属性。

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

答案 3 :(得分:2)

按照你所描述的那样累积列表的速度,性能会降低很长一段时间。并且硬件和软件性能提高得更快。

在你确定需要它之前不要做一些复杂的事情,简单的事情就行不通。把它放在一张桌子里。请参阅有关pessimizations的问题 - 这是一个。

答案 4 :(得分:1)

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

所有旧记录都会导致表格大小不断增长,这意味着查询速度变慢,即使查询优化也是如此。

编辑: 正如其他人提到的那样,如果您计划经常组合实时数据和存档数据,那么这种方法的一个重要方面就是如此。如果你总是单独引用它们而不是很好,但如果没有,你将需要大量的连接和联合将数据拉到一起 - 这是不理想的。

答案 5 :(得分:1)

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

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

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

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

答案 6 :(得分:1)

以下是我的理解:

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

如果我理解上述内容,下一个问题是您使用过期数据的频率是多少?它用于什么?就像@ghills指出的那样,sql-unions可能会让你失望。

如果过期数据不需要联机,则将其存档到单独的表中可能是有意义的。特别是如果过期行的数量超过活动行数#。

如果将它们保存在同一个表中,“where expired = false”可能最终成为您的常量伴侣,并且由于选择性将很低(即大量过期行),“过期”列上的索引将无法获取你赚了很多钱。 (Oracle有位图索引 - 但这可能根本不适用于此处。)

答案 7 :(得分:1)

我会把它们放在一张桌子里。否则,(a)您有两个具有相同列的表。每当您对数据进行更改时,您都必须记住以相同的方式更改两个表。迟早有人会忘记 - 或者明白一个表中的数据在另一个表中是不需要的 - 而现在你的设计变得更复杂了。很快你就会写两次完全相同的逻辑:一次从“当前”表中检索并再次从“归档”表中检索。但是后来有人对一段代码进行了更改,并忘记对另一段代码进行相同的更改。然后下一个出现的人不能确定他们是否不同,因为有充分的理由说明他们应该是不同的,或者有人忘了。等等(b)看起来你可能会想要查看两个表格的查询,例如“告诉我过去12个月内要价超过20,000美元的所有广告”,其中一些广告可能是最新的,其他广告可能是最新的存档。这些查询现在是联合或复杂的联接,而不是简单地不包括“expired is true”或“expired is false”标记。

关于性能问题,这很简单:创建一个包含您需要包含的内容的多字段键。过期+价格或过期+ modelname似乎很可能是关键。您可能希望首先过期,因为您的大多数查询可能都需要非过期记录,但我只是猜测。选择值得索引的是一个复杂的决策,但是当在多个字段上有明显的常见查询时,就这样做。

答案 8 :(得分:0)

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