我想知道以下情况的最佳方法是什么:
我在数据库中有一个显然包含所有订单的Orders表。但这些都是字面上的所有订单,因此包括刚刚标记为“完整”的完整/已完成订单。从所有未结订单我想要计算一些东西(如开放金额,未清项目等)。什么会更好的表现明智:
将1个订单表保留所有订单,包括完整/存档订单,并通过过滤“完整”标记进行计算?
或者我应该创建另一个表格,例如'Orders_Archive',以便Orders表只包含我用于计算的未结订单?
这些方法中是否有(明显的)性能差异?
(B.T.W。我正在使用PostgreSQL数据库。)
答案 0 :(得分:7)
这是数据库设计中的常见问题:是否要分离或“归档”不再“活动”的记录的问题。
最常见的方法是:
最后一种方法结合了前两种方法的优点,但需要DBMS支持,设置起来比较复杂。
注意:
仅存储“存档”数据的表通常称为“存档表”。有些DBMS甚至为这些表(例如MySQL)提供了特殊的存储引擎,这些表经过优化,可以快速检索和提高存储效率,但代价是缓慢的更改/插入。
答案 1 :(得分:6)
或者我应该创建另一个表格,例如'Orders_Archive',以便Orders表只包含我用于计算的未结订单?
是。他们称之为数据仓库。人们这样做是因为它加速了交易系统,以消除几乎没有用过的历史。首先,表格在物理上更小,处理速度更快。其次,长期运行的历史报告不会干扰事务处理。
这些方法中是否有(明显的)性能差异?
是。奖金。您可以重新构建历史记录,使其不再是3NF(用于更新),而是用于星型模式(用于报告)。优点是巨大的。
购买Kimball的数据仓库工具包一书,了解有关星型模式设计的更多信息,并将历史记录从活动表迁移到仓库表中。
答案 2 :(得分:4)
从不拆分或分离当前/存档数据。这完全是不正确的。它可能被称为“数据仓库”或一桶鱼,但它是错误的,不必要的,并且创建其他方面没有的问题。结果是:
如果且仅当表上的响应很慢时,则解决该问题,并提高速度。只要。没有其他的。这(在我看到的每种情况下)都是索引错误(缺少索引或不正确的列或不正确的列序列都是错误)。通常,您需要的只是索引中的IsComplete列,以及您的用户用于搜索最频繁的任何内容,进入/排除开放/完成订单。
现在,如果您的dbms平台无法处理大型表或大型结果集,那么这是一个不同的问题,您必须使用该工具中可用的任何方法。但作为一个数据库设计问题,这是完全错误的;除非您受到平台的限制,否则无需创建副本,填充和维护副本(包含所有后续问题)。
去年和今年,作为普通性能分配的一部分,我已经整合了数十亿行的拆分表(并且必须解决所谓的“不存在”的所有重复行问题,是的,2天只是为了那个)。具有更正指数的合并表比拆分表更快; “数十亿行放慢桌面速度”的借口完全是错误的。用户爱我,因为他们不再需要使用两个工具并查询两个“数据库”来获得他们需要的东西。
答案 3 :(得分:1)
由于您使用的是postgresql,因此您可以利用部分索引。假设对于未完成的订单,您经常使用 orderdate ,您可以像这样指定索引:
create index order_orderdate_unfinished_ix on orders ( orderdate )
where completed is null or completed = 'f';
当您放置该条件时,postgresql将不会索引已完成的订单,从而节省了硬盘空间并使索引更快,因为它只包含少量数据。因此,您可以在没有桌子分离麻烦的情况下获得好处。
将数据分成ORDERS和ORDERS_ARCHIVE时,您必须调整现有报告。如果您有很多报告,那可能会很痛苦。
请参阅此页面中部分索引的完整说明:http://www.postgresql.org/docs/9.0/static/indexes-partial.html
编辑:对于存档,我更喜欢创建具有相同模式的另一个数据库,然后将旧数据从事务数据库移动到此存档数据库。