Это вопрос о компромиссах.
Представьте себе социальную сеть. У каждого пользователя есть статусное сообщение, которое он может изменить в любое время. Всякий раз, когда он это меняет, все его друзья получают уведомление через стену (как в Facebook).
Чтобы сделать эту работу. У нас есть 3 таблицы Users (id, name), FriendLists (userId, friendUserId), Уведомления (?).
Теперь давайте предположим, что у каждого пользователя есть приблизительно 50 друзей в его списке друзей. Я столкнулся с дилеммой - как реализовать таблицу уведомлений.
1-й вариант
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.
2-й вариант
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
Так что вы думаете по этому поводу?