这是一个关于权衡的问题。
想象一个社交网络。每个用户都有一条状态消息,他可以随时更改。每当他改变它时,他所有的朋友都会通过一堵墙得到通知(比如在 Facebook 中)。
使这项工作。我们有 3 个表 Users(id, name), FriendLists(userId,friendUserId), Notifications(?)。
现在让我们假设每个用户在他的朋友列表中大约有 50 个朋友。我面临着两难境地——如何实现通知表。
第一个选项
CREATE TABLE Notifications
(
toUserId bigint NOT NULL,
[identity] bigint IDENTITY(1,1) NOT NULL,
fromUserId bigint NOT NULL,
data varchar(256) NOT NULL,
CONSTRAINT [PK_Notifications] PRIMARY KEY CLUSTERED (toUserId, [identity])
)
发送通知:
-- Get all friends of @fromUserId.
WITH Friends AS
(SELECT FriendLists.friendUserId
FROM FriendLists
WHERE userId = @fromUserId)
-- Send updates to all friends.
SELECT
friendUserId as toUserId,
@fromUserId as fromUserId,
@data as data
INTO Notifications
FROM Friends
在这种情况下,对于每个状态更改,我们创建 50 条记录(假设有 50 个朋友)。这是不好的。然而,好的一点是检索特定用户的通知非常快,因为我们在 toUserId 上有一个聚集索引。
第二个选项
CREATE TABLE Notifications
(
toUserId bigint NOT NULL,
[identity] bigint IDENTITY(1,1) NOT NULL,
fromUserId bigint NOT NULL,
data varchar(256) NOT NULL,
CONSTRAINT [PK_Notifications] PRIMARY KEY CLUSTERED ([identity])
)
CREATE NONCLUSTERED INDEX [IX_toUserId] ON Notifications (toUserId ASC)
发送通知:
-- Get all friends of @fromUserId.
WITH Friends AS
(SELECT FriendLists.friendUserId
FROM FriendLists
WHERE userId = @fromUserId)
-- Send updates to all friends.
INSERT INTO Notifications(toUserId, fromUserId, data)
VALUES(friendUserId, @fromUserId, @data)
在这里,我们每次状态更新只插入一条记录。这很好。不好的一点是通知的检索会变慢,因为记录不是由 toUserId 聚集的。
两种方法获取通知是相同的:
SELECT TOP(50) fromUserId, [identity], data
FROM Notifications
WHERE toUserId = @toUserId
那么您对此有何看法?