Sql server 慢更新vs慢选择

Sql server 慢更新vs慢选择,sql-server,indexing,tradeoff,Sql Server,Indexing,Tradeoff,这是一个关于权衡的问题 想象一下一个社交网络。每个用户都有一条状态消息,可以随时更改。每当他改变它时,他所有的朋友都会通过一堵墙得到通知(就像在Facebook上) 让这一切顺利进行。我们有3个表用户(id,name),朋友列表(userId,friendUserId),通知(?) 现在让我们假设每个用户的好友列表中大约有50个好友。我面临着两难境地——如何实现通知表 第一选项 发送通知: -- Get all friends of @fromUserId. WITH Friends AS

这是一个关于权衡的问题

想象一下一个社交网络。每个用户都有一条状态消息,可以随时更改。每当他改变它时,他所有的朋友都会通过一堵墙得到通知(就像在Facebook上)

让这一切顺利进行。我们有3个表用户(id,name),朋友列表(userId,friendUserId),通知(?)

现在让我们假设每个用户的好友列表中大约有50个好友。我面临着两难境地——如何实现通知表


第一选项 发送通知:

-- 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
-- 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)
在这种情况下,我们为每个状态更改创建50条记录(假设有50个朋友)。这很糟糕。然而,好的一点是,检索特定用户的通知非常快,因为我们在toUserId上有一个聚集索引

第二种选择 发送通知:

-- 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
-- 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

那么您对此有何看法?

与选择相比,更新速度非常慢。。。几个数量级。此外,随着站点规模的扩大,您将在内存中缓存所有回迁,因此选择的速度将很小。

在这种情况下,在(toUser,identity)上创建聚集索引似乎不是一个好主意,因为聚集索引确实应该按升序插入。当然,SQL将负责保持表的排序,但这会带来很高的性能成本(这是您的问题所在)。但一般来说,对于聚集索引,不建议提前知道没有特定顺序的插入。下面是一个关于聚集索引建议的非常好的例子

话虽如此,我还是坚持使用identity列作为聚集索引,并在tuserid上创建一个非聚集索引,也许还有一个datetime列。通过包含datetime列,可以更高效地查询最近的数据

关于缓慢更新,社交网站上的状态更新对于消息队列来说是一个完美的情况。这样,您就可以根据需要对数据库进行调优,以加快读取速度,如果它对写入性能有影响,用户就不必受到影响。从他们的角度来看,更新是即时的,尽管可能需要一些时间才能“坚持”


对于非常大的数据库,我将听从SQL专家的建议,他们可以讨论分区策略(对于较新的数据,较小的表更易于管理,对于较旧的数据,较大的表/索引较多的表)和复制解决方案。

首先,与写入相比,读取总是非常困难,因为每堵“墙”被看到的次数要比更新的次数多得多。所以你最好快点读

其次,这些大型社交网站固有的一个问题是数据的分布(分片、分区,没有一个数据库能够存储所有帐户、所有好友、所有通知),这意味着当一个新的通知挂在墙上时,必须在其他服务器上通知好友。这意味着无论如何更新都是异步的和基于消息传递的

所以我肯定会选择一个适合阅读的结构


我建议你仔细阅读参与Facebook和MySpace等网站架构的不同人士所做的公开演讲,比如。他们解释了设计中的许多思考和推理。

很好的链接。非常感谢。我还发现了这个和这个。如果你有更多关于这个话题的有用信息,请分享。