【问题标题】:Enhancing performance of SQL query提高 SQL 查询的性能
【发布时间】:2017-05-26 06:02:34
【问题描述】:

我正在对三个表 messagesmessage_recipientsusers 运行查询。

messages表的表结构:

id int pk
message_id int
message text
user_id int
...

此表的索引位于 user_idmessage_idid

message_recipients表的表结构:

id int pk
message_id int
read_date datetime
user_id int
...

索引位于idmessage_iduser_id

users表的表结构:

id int pk
display_name varchar
...

索引位于id

我正在对这些表运行以下查询:

SELECT 
    m.*, 
    if(m.user_id = 0, 'Campus Manager', u.display_name) AS name,
    mr.read_date, 
    IF(m1.message_id > 0 and m1.user_id=1, true, false) as replied 
FROM 
    messages m 
JOIN 
    message_recipients mr 
ON 
    mr.message_id = m.id 
LEFT JOIN 
    users u 
ON 
    u.UID = m.user_id 
LEFT JOIN 
    messages m1 
ON 
    m1.message_id = m.id 
WHERE 
    mr.user_id = 1 
AND 
    m.published = 1 
GROUP BY 
    mr.message_id 
ORDER BY 
    m.created DESC

EXPLAIN为此查询返回以下数据:

更新 正如@e4c5 所建议的,我在 (published,user_id,created) 上添加了新的复合索引,现在解释查询显示了这一点:

如何通过添加所需的索引(如果有)来优化此查询,因为它需要很多时间?

【问题讨论】:

    标签: mysql database join indexing query-optimization


    【解决方案1】:
    • GROUP BY 需要列出所有非聚合列。我怀疑那会是一团糟。为什么你需要GROUP BY
    • 为什么要将messages.id 链接到messages_id?这是一个分层表,但列名不像'parent_id'?
    • “索引在 id、message_id 和 user_id 上”——这是一个复合索引还是 3 个单列索引? (这有很大的不同。)最好向我们展示SHOW CREATE TABLE 而不是模棱两可的释义。
    • user_id=1 多产吗?也就是说,您是否期望有数千行?这个查询只是他的问题吗?
    • 使用LEFT JOIN 意味着m1.message_id 可能是NULL,但对它的引用似乎忽略了这种可能性。
    • 如果这是一个包含消息线程的单个表——关于线程的主要信息和各个响应,那么我认为这是一个糟糕的设计。 (我曾经犯过这个错误。)我认为最好有一个每个线程一行的表格和另一个每个评论一行的表格。 1 个线程:许多 cmets。所以评论表中会有一个thread_id。

    【讨论】:

    • 分组依据是必要的以避免重复。它是一个分层表,回复消息的id 将发送到message_id。不,有三个单独的索引。不,问题在于每个用户,而不仅仅是单个用户。是的m1.message_id 可以是null,表示该消息尚未回复。没有什么类似于消息线程,只是作为对特定消息的回复而发送的消息的id
    【解决方案2】:

    通过向messagesmessage_recipients 表添加新索引并将messages 表的数据库引擎从InnoDB 更改为MyISAM,我能够将查询时间从3 秒缩短到0.1 秒.

    在这些列上添加了复合索引 composite,并在 messages 表上分别按顺序排列 - published, user_id, created

    message_recipients 表的两列上添加了复合索引message_id_2 - message_id, user_id

    EXPLAIN 查询现在显示

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多