10

在我的数据库设计中使用高级别的冗余、非规范化数据来提高性能。我会经常存储通常需要连接或计算的数据。例如,如果我有一个User表和一个Task表,我会在每个Task记录中冗余地存储UsernameUserDisplayName 。另一个示例是存储聚合,例如将TaskCount存储在User表中。

  • 用户
    • 用户身份
    • 用户名
    • 用户显示名称
    • 任务计数
  • 任务
    • 任务ID
    • 任务名称
    • 用户身份
    • 用户名
    • 用户显示名称

这对性能很有好处,因为应用程序的读取次数比插入、更新或删除操作多得多,而且像用户名这样的一些值很少更改。但是,最大的缺点是必须通过应用程序代码或触发器来强制执行完整性。这对于更新来说可能非常麻烦。

我的问题是这可以在 SQL Server 2005/2010 中自动完成......也许通过持久/永久视图。有人会推荐另一种可能的解决方案或技术吗?我听说 CouchDB 和 MongoDB 等基于文档的数据库可以更有效地处理非规范化数据。

4

1 回答 1

11

在迁移到 NoSQL 解决方案之前,您可能需要先尝试索引视图:

http://msdn.microsoft.com/en-us/library/ms187864.aspx

和:

http://msdn.microsoft.com/en-us/library/ms191432.aspx

使用索引视图将允许您将基础数据保存在正确规范化的表中并保持数据完整性,同时为您提供该数据的非规范化“视图”。对于高度事务性的表,我不建议这样做,但是您说读取比写入更重,因此您可能想看看这是否适合您。

根据您的两个示例表,一个选项是:

1)向定义为的用户表添加一列:

TaskCount INT NOT NULL DEFAULT (0)

2)在定义为的任务表上添加触发器:

CREATE TRIGGER UpdateUserTaskCount
ON dbo.Task
AFTER INSERT, DELETE
AS

;WITH added AS
(
    SELECT  ins.UserID, COUNT(*) AS [NumTasks]
    FROM    INSERTED ins
    GROUP BY    ins.UserID
)
UPDATE  usr
SET     usr.TaskCount = (usr.TaskCount + added.NumTasks)
FROM    dbo.[User] usr
INNER JOIN  added
        ON  added.UserID = usr.UserID


;WITH removed AS
(
    SELECT  del.UserID, COUNT(*) AS [NumTasks]
    FROM    DELETED del
    GROUP BY    del.UserID
)
UPDATE  usr
SET     usr.TaskCount = (usr.TaskCount - removed.NumTasks)
FROM    dbo.[User] usr
INNER JOIN  removed
        ON  removed.UserID = usr.UserID
GO

3)然后做一个视图:

SELECT   u.UserID,
         u.Username,
         u.UserDisplayName,
         u.TaskCount,
         t.TaskID,
         t.TaskName
FROM     User u
INNER JOIN   Task t
        ON   t.UserID = u.UserID

然后按照上面链接中的建议(WITH SCHEMABINDING、唯一聚集索引等)使其“持久化”。虽然如上所示在 SELECT 中的子查询中进行聚合是低效的,但这种特定情况旨在在读取高于写入的情况下进行非规范化。因此,索引视图将保持整个结构(包括聚合)物理存储,因此每次读取都不会重新计算它。

现在,如果在某些用户没有任何任务的情况下需要 LEFT JOIN,那么由于创建它们的 5000 个限制,索引视图将无法工作。在这种情况下,您可以创建一个真实表(UserTask),它是您的非规范化结构,并通过仅用户表上的触发器填充它(假设您执行上面显示的触发器,它根据更改更新用户表任务表),或者您可以跳过用户表中的任务计数字段,只在两个表上使用触发器来填充用户任务表。最后,这基本上就是索引视图所做的事情,而无需编写同步触发器。

于 2011-01-25T02:08:05.097 回答