English 中文(简体)
SQL查询——如何有效地获取non-read消息
原标题:
  • 时间:2009-03-22 00:33:50
  •  标签:

我如何最好的收集给定用户未读的消息吗?

现有表

Message table
----------------------------------
id    title    body    sentAt

User table
----------------------------------
id    username

Read Messages table
----------------------------------
user_id    message_id

我想类似

select 
  m.id, m.title, m.sentAt, u.username
from 
  message m,
  [user] u
where 
  u.id = 1 and -- @userId parameter
  m.id not in 
    (select r.message_id from read_messages r where r.user_id = u.id)

不幸的是我我不理解多观察执行计划。/亚当

最佳回答

< em >提出另一种方法:< / em >

我在工作中面临着相同的问题。我浪费了一个好周想弄最好的方法。我最终创建一个连接表,你所做的,但表只包含< em >未读< / em >消息,而不是跟踪< em > < / em >阅读消息。

Because

  1. The status quo is "everyone has read all their messages".
  2. Getting the unread messages (or their count) should be as fast as possible.
  3. The status quo should be the least straining status on the system.

现在,如果我将ve记录所有消息每个人都读过,数据库中的杂物迅速增长(< em > < / em >用户* < em > < / em >行)的消息,容易导致成千上万行重量更小的应用程序。这个问题被夸大了的一生如果消息不确定,您可以跟踪消息状态很多岁。

如果跟踪逆,你的“未读消息”表仅包含少量的行,并减少用户读取的每个消息。获得未读消息的数量也很简单,“<代码> SELECT COUNT(*)从用户未读的地方= foo > < /代码”。

But

一切,这是一种折衷。而阅读是几乎一样快计算,写作是一件苦差事。对于每个写消息,您需要插入一个条目连接表。另外,如果多人可以读取相同的消息,您需要为每个收件人插入一行。如果收件人是隐式(如只有一个用户组名称,甚至与标准如“谁有权访问这个东西”),创建新消息变得更加复杂。

但我觉得这是一个公平的妥协。

YMMV, HTH.

问题回答

不是非常昂贵。相反,你可以做一些类似:

SELECT
  m.id, m.title, m.sentAt
FROM
  message m
  LEFT JOIN [Read Messages] rm
    ON m.message_id = rm.message_id AND rm.user_id = @userID
WHERE
  rm.user_id IS NULL

如果你有正确的索引,这应该是快得多。

你获取用户的所有消息,加入阅读消息。在WHERE子句中,你要求,user_id空消息,这意味着用户还没有读它。

惠普年代替代的建议是最有可能适合你。然而,如果不是,我建议使用不存在而不是离开加入如果它可能在您的环境中。

至少在MS SQL,将给一个稍微便宜的查询计划,因为它不需要最后过滤(user_id为空)

SELECT  ...
FROM    message m
WHERE   NOT EXISTS (
    SELECT 1
    FROM    read_messages rm
    WHERE   rm.usr_id = ...
    AND rm.msg_id = m.msg_id
)




相关问题
热门标签