SQL 查询 - 如何有效地获取未读消息

标签 sql

如何最好地收集给定用户尚未阅读的消息?

现有表

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)

不幸的是,对我来说,我不太了解执行计划。/亚当

最佳答案

建议替代方法:

我之前在工作中遇到过完全相同的问题。我浪费了一周的时间来试图找出最好的方法来做到这一点。正如您所做的那样,我最终创建了一个连接表,但该表仅包含未读消息,而不是跟踪已读消息。

因为

  • 现状是“每个人都阅读了他们的所有消息”。
  • 获取未读消息(或它们的计数)应该尽可能快。
  • 现状应该是对系统压力最小的状态。

  • 现在,如果我一直跟踪每个人阅读过的所有消息,数据库中的困惑会增长得非常快(用户*消息行),在更小的应用程序中很容易导致数千行“死重”。如果消息的生命周期是不确定的,这个问题就会被夸大——您可能要跟踪多年以前的消息状态。

    如果跟踪相反,您的“未读消息”表只包含少数行,并且随着用户阅读的每条消息它们减少。此外,获取未读消息的数量就像“SELECT COUNT(*) FROM unread WHERE user = foo”一样简单。



    与所有事情一样,这是一种权衡。虽然阅读在计算上尽可能快,但写作是一件苦差事。对于每条书面消息,您都需要在此连接表中插入一个条目。此外,如果多人可以阅读同一封邮件,您需要为每个收件人插入一行。如果收件人是隐式的(例如,只给出了用户组的名称,或者甚至使用了诸如“有权访问此内容的任何人”之类的标准),则创建新消息会变得更加复杂。

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

    YMMV,HTH。

    关于SQL 查询 - 如何有效地获取未读消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/670327/

    相关文章:

    php - 用于从 SET 列中获取最常用项目的 SQL 查询

    sql - 将电话号码与单元格中的字符串分开 - 随机顺序

    android - 活跃的Android多对多关系

    mysql - 此查询仍返回空标题字段?

    mysql - 使用 java.sql.TimeStamp 和 mysql 数据库遇到的奇怪行为

    phpmyAdmin 错误我不明白

    sql - 正确使用联接

    sql - 在 T-SQL 中替换没有游标的字符串中出现的字符串列表

    mysql - 使用 SQL 查找每个司机一个月内的平均预订评分

    sql - 如何使用更新表上的多个联接更新 SQL Server 上的表? (从加入)