交易和报告数据库 - 如何?

时间:2010-10-06 13:33:38

标签: .net sql-server database

构建具有高度规范化数据库的事务系统时,运行报告样式查询,甚至在UI上显示数据的查询都可能涉及多个联接,这在数据繁重的情况下可以并且通常会影响性能。加入很贵。

通常,所提供的指导是您永远不应该从事务性数据库模型中运行这些查询,而应该使用针对特定UI视图或报告而定制的非规范化展平模型,从而消除了对许多联接的需要。在这种情况下,数据复制不是问题。

这个概念非常有意义,但是当专家发表这些陈述时我很少看到的是如何实现这一点。例如,(并且坦率地说,我很欣赏使用任何平台的示例)在sql server后端运行的中型系统中,您有一个规范化的事务模型。您还有一些报告和需要查询的网站。因此,您创建了一个“报告”数据库,可以平滑规范化数据。你如何保持同步?交易日志运送?如果是这样,您如何转换数据以适应报告模型?

5 个答案:

答案 0 :(得分:3)

在我们的商店中,我们设置了从OLTP系统到另一个用于报告的数据库服务器的连续transactional replication。您不希望为此目的使用日志传送,因为每次还原日志时都需要对数据库进行独占锁定,这会阻止用户运行报告。

今天使用SQL Server中的优化器,我认为规范化数据库上的连接对于报告而言“太昂贵”这一概念有点过时了。我们的设计完全是第3范式,主表中有数百万行,运行任何报告都没有问题。话虽如此,如果推动推动,您可以考虑在报告服务器上创建一些indexed views来帮助解决。

答案 1 :(得分:0)

我们使用事务复制到另一个数据库。

我们过滤数据,因此我们只获取复制数据库中需要的数据

我们也只选择我们想要的列,因此表格更小。

然后我们通过视图组合复制数据库中的数据,或者我们构建触发器以将数据从一个表添加到另一个表。

答案 2 :(得分:0)

Canned answer

在很多情况下,索引视图可能会解决您的短期绩效目标,但在以后某些时候会产生适得其反的效果。因此,如果您选择使用索引视图,则可能需要退出策略。让我用索引视图描述一些常见问题。

索引视图可能会增加锁争用。

很容易证明。创建下表:

CREATE TABLE dbo.ChildTable(ChildID INT NOT NULL 
  CONSTRAINT PK_ChildTable PRIMARY KEY,
  ParentID INT NOT NULL,
  Amount INT NOT NULL);
GO   

从SSMS中的一个选项卡中,运行以下脚本:

BEGIN TRAN;
INSERT INTO dbo.ChildTable(ChildID, ParentID, Amount)
  VALUES(1,1,1); 

从另一个标签中,运行类似的标签:

BEGIN TRAN;
INSERT INTO dbo.ChildTable(ChildID, ParentID, Amount)
  VALUES(2,1,1);
ROLLBACK;

请注意,两个插入完成后,它们不会相互阻塞。在两个选项卡中回滚,并创建索引视图:

CREATE VIEW dbo.ChildTableTotals WITH SCHEMABINDING
AS
SELECT ParentID, 
  COUNT_BIG(*) AS ChildRowsPerParent, 
  SUM(Amount) AS SumAmount
FROM dbo.ChildTable
GROUP BY ParentID;
GO
CREATE UNIQUE CLUSTERED INDEX ChildTableTotals_CI 
  ON dbo.ChildTableTotals(ParentID);

重新运行两个插页。请注意,第二个没有完成;它被封锁了。原因很简单:第一个插入修改索引视图中的相应条目,因此插入获取并保持锁定。

同样容易证明,当您创建索引视图时,死锁也可能变得更加可能。

注意:这不是索引视图实现方式的问题。如果您推出自己的摘要表,并开发直接修改它以使其保持最新的触发器,您将遇到相同的问题。只有当你不一直维护你的汇总表时,你才能解决这个锁定问题,但是对此更详细的讨论超出了本文的范围。

编辑:这个例子可能看起来很狡猾,但它演示的问题非常真实且非常常见。 OLTP环境中的索引视图使用受到限制,因为它们会严重增加锁争用并导致许多死锁。有人在OLTP中创建它们是很常见的,但最终会下降,因为它们引入的问题比它们解决的问题要多。

有两种常见的方法来演示并发引起的问题 - 我们要么编写循环并从多个连接运行它们,要么显式地在两个或多个连接中开始事务。我鼓励每个人想出一个更简单的方法来证明这个问题。

答案 3 :(得分:0)

正确的索引,覆盖索引和重新格式化查询可能会给您带来很多好处。但是,如果您已经这样做了,那么您可以镜像数据库,复制它们,或者创建一个etl包并创建一个分析服务多维数据集。

答案 4 :(得分:-1)

简短回答:尝试使用indexed views。基础表有许多限制,但您可以开箱即用地进行同步。