【问题标题】:How should I index my tables and build my request to improve perfomance?我应该如何索引我的表并构建我的请求以提高性能?
【发布时间】:2021-10-18 01:23:54
【问题描述】:

我正在使用 MySQL。对于 MP 系统,我有两个表(+1 列出对话):

_ msg_individus (= members of a conversation)
mi_mcid : id of the conversation
mi_uid : id of the user
mi_ustatus : status of the conversation for the user (opened or closed)
mi_datelecture : the last time (timestamp) the user opened the conversation

现在我将mi_mcid 和mi_muid 索引为主键。

_ msg_messages (= messages of the conversation)
msg_id : id of the message
msg_uid : id of the user who wrote the message
msg_mcid : id of the conversation
msg_text : content of the message
msg_timestamp : when the message was posted

现在我将msg_id 作为主键,msg_mcid 作为索引。

事情是这样的:我想知道是否有用户未读的消息。为此,我比较了最后一个 msg_timestamp 和 mi_datelecture,如果第一个大于第二个,那么就有了新的东西。

但由于某种原因,此请求的性能非常糟糕,我无法弄清楚如何正确索引以及如何以最佳方式构建我的请求以提高性能。

这是我构建的:

SELECT 1 FROM msg_messages as msg
WHERE msg.msg_uid != :u_id
  AND msg.msg_status = "1"
  AND msg.msg_mcid IN (SELECT mi.mi_mcid
         FROM msg_individus as mi
         WHERE mi.mi_uid = :uid
           AND mi.mi_ustatus = "2"
           AND mi.mi_datelecture < msg.msg_timestamp)
LIMIT 0,1

例如,我尝试在msg_status、mi_uid、mi_status 上设置一些索引,但即使情况稍微好一点,性能也很难过哈哈。当我不比较 mi_datelecture 和 msg_timestamp 时,处理大约需要 0.05 秒,而我这样做需要 0.20 秒。

感谢您的建议。

(来自评论)新尝试:

SELECT  1
    FROM  msg_messages as msg
    WHERE  msg.msg_uid != :u_id
      AND  msg.msg_status = "1"
      AND  EXISTS 
    (
        SELECT  *
            FROM  msg_individus as mi
            WHERE  mi.mi_mcid = msg.msg_mcid
              AND  mi.mi_uid = :uid
              AND  mi.mi_ustatus = "2"
              AND  (mi.mi_datelecture = "0"
                      OR  mi.mi_datelecture < msg.msg_timestamp)
    )
    LIMIT  0,1

【问题讨论】:

  • 您正在查询msg_timestamp。当然,很明显您应该在此基础上建立一个索引,但您似乎已经尝试了所有方法。
  • 您是否正在查看一个用户可能参与的所有对话?如果是这样,您不需要对话列表吗?还是只是一个特定的对话?如果是这样,那么查询中的msg_id 在哪里?
  • @TangentiallyPerpendicular 是的,我试过了^^
  • @RickJames 实际上我并不关心什么消息,甚至什么对话是新的,在这种情况下,我只是想知道用户是否有新消息

标签: mysql indexing query-optimization


【解决方案1】:

创建此索引。

CREATE INDEX ON msg_individus
  (mi_uid, mi_ustatus, mi_datelecture, mi_mcid );

它是一个适合您的子查询的覆盖索引。从索引可以完全满足子查询。

如果您需要更多帮助read this,请再问一个问题。

【讨论】:

  • 谢谢。我已经试过了,但我又试了一次,即使它好一点,它仍然不是那么好。
【解决方案2】:

如果您只需要“存在”,请使用EXISTS ( SELECT 1 ... ) 而不是LIMIT 1。

将IN ( SELECT ... ) 更改为JOIN 或EXISTS ( SELECT 1 ... );两者都可能更快。

并查看我的评论,该评论会思考查询甚至提供所需信息的位置。

那么我们可以而且应该讨论索引。

【讨论】:

  • 上班前,我创建了这些索引:mi_uid+mi_ustatus+mi_datelecture+mi_mcid 和msg_uid+msg_mcid+msg_statut+msg_timestamp我将查询更改为 SELECT 1 FROM msg_messages as msg WHERE msg.msg_uid != :u_id AND msg.msg_status = "1" AND EXISTS (SELECT * FROM msg_individus as mi WHERE mi.mi_mcid = msg.msg_mcid AND mi.mi_uid = :uid AND mi.mi_ustatus = "2" AND (mi.mi_datelecture = "0" OR mi.mi_datelecture &lt; msg.msg_timestamp)) LIMIT 0,1 之类的东西,情况已经好转(处理 0.013 秒)。但是我一回到家就试试你的建议
  • @Vae - 该版本引入了一个新问题——OR。将其拆分为两个EXIST ( SELECT ... )
猜你喜欢
  • 2012-10-20
  • 2022-01-17
  • 2015-06-04
  • 1970-01-01
  • 1970-01-01
  • 2013-10-15
  • 2011-06-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多