1

我有一项很常见的任务是在我们的 Web 应用程序(asp.net + mssql)中显示销售历史。我有一张桌子,上面有销售交易,比如:

 - SellerID (string)
 - Product PartNumber
 - Product ManufacturerName
 - ProductID (string uniq normalized PN+MN)
 - Date of sale
 - Price
 - Qty
 - Option 1
 - Option 2
 - Option 3

选项是一些特定的属性(如合同号等)。

我需要显示按 productID 分组的销售数据,其中包含 Qty 和 Amount 的总和。我还需要提供按 SellerId、Date 和 Options 过滤的能力。所以用户应该看到表格:

 - Part Number
 - Manufacturer Name
 - Sum(Qty)
 - Sum(Price)

用户还可以按显示的列进行排序和过滤并浏览页面

目前我们有大约 500 万条销售记录,而带有这种分组、过滤和排序的“直接”查询需要太多时间(并且没有考虑到这个 Web 服务可以被多个并发用户使用)。

为了让它更快地工作,我们过去常常根据查询中使用的所有条件创建一个缓存键,并使用相同的方案(加上缓存键)将查询的整个结果复制到缓存表中。但是有一些缺点,例如缓存表的快速增长,以及在缓存表中创建不规则的困难(它会减慢插入速度)

我很确定对于大多数与销售相关的业务应用程序来说,这项任务是非常普遍和著名的。

人们如何解决所有这些问题?

UPD:我忘了提。

  1. 没有插入销售数据(我们过去每季度手动加载一次)

  2. 我在考虑 olap,但从未真正使用过它。使用 olap 有意义吗?

  3. 我们不受 SQL Server 的严格限制,如果有意义,我们可以使用任何其他数据库

4

1 回答 1

2

您的问题的解决方案取决于查询和数据结构的组合。

对于您所描述的内容,自然格式将是星型模式,中间有一个事实表。但是,事实表可能与您现在拥有的非常接近。不同之处在于记录的大小。事实记录会将大部分“可读”内容移动到引用表中,因此每条记录都尽可能小。它可能看起来像:

  • SellerID -- 整数 id
  • ProductID -- 整数 ID
  • 销售日期
  • 价格
  • 数量
  • 选项 1——smallint
  • 选项 2——smallint
  • 选项 3——smallint

像:

  • 产品零件号
  • 产品制造商名称
  • 卖家姓名

将在参考表中。

这本身可能会将事实表缩小到适合您的缓存的大小。

接下来,开始在其上构建索引。您可能需要多个索引,具体取决于过滤条件: (date, salesid, productid, option1, option2, option3)(productid, date)等。我意识到索引确实需要在插入方面付出额外的努力。影响取决于每天的插入次数。对于决策支持系统,您应该能够忍受“数据滞后”,即定期更新数据。批量插入有助于索引构建开销。

如果您的要求是实时报告,请考虑对数据进行分区,以便最新数据位于一个小分区中。分区索引更小,因此插入的开销应该更小。

而且,如果您的需求真的很重——每分钟大量实时更新、大量实时报告切片和切块,以及大量需要完整历史记录的查询——那么投资更多内存,以便表格可以轻松放入记忆。在此过程中,您可以优化中央数据结构,使其由 id 和数字数量组成,并使用包含附加数据的参考表。主键上的连接将比存储数据更快,否则会大很多倍。

于 2013-07-21T00:31:23.833 回答