【问题标题】:Slow SQL query with LEFT JOIN使用 LEFT JOIN 的慢速 SQL 查询
【发布时间】:2019-03-07 09:03:48
【问题描述】:

我已经阅读过类似的问题,但对我没有帮助。

我有疑问

SELECT `login`, 
   `photo`, 
   `username`, 
   `user`.`id`, 
   `name`, 
   `msg_info` 
FROM   `user` 
       LEFT JOIN `friends` 
              ON `friends`.`child` = `user`.`fb_id` 
WHERE  `friends`.`parent` = '1111' 
ORDER  BY `msg_info` DESC 

这需要 0.7411 秒(甚至更多)

它显示 总共 158 行 行(好吧我可以限制它,但查询仍然很慢)

friendsuser 表中的每一个都有超过 200.000 行

我该怎么做才能让查询更快?

谢谢!

【问题讨论】:

  • 你必须使用order by吗?
  • 在那里使用 LEFT JOIN 毫无意义 - 你的 where 子句让它作为 INNER JOIN 运行
  • 限定所有列,这样我们就知道列属于哪个表,即到处都是tablename.columnname。
  • MassiveOwl,你说得对,我取消了订单,一切都变得美好!谢谢!
  • @CaiusJard 也许他需要将 friends.parent = 1111 放在 ON 子句而不是 WHERE 子句中,并且仍然想要左连接。

标签: mysql sql performance join


【解决方案1】:

正如@MrVimes 建议的那样,有时在 JOIN 子句中添加条件会产生很大的不同:

SELECT login, photo, username, user.id, name, msg_info
FROM user u
INNER JOIN friends f ON f.child = u.fb_id AND f.parent = '1111'
ORDER BY msg_info DESC;

当然,假设您的所有 PK 和 FK 都已正确定义和索引。

【讨论】:

    【解决方案2】:

    正如 cmets 所指出的,您的左连接实际上与以下内连接查询没有什么不同:

    SELECT
        login,
        photo,
        username,
        user.id,
        name,
        msg_info
    FROM user u
    INNER JOIN friends f
        ON f.child = u.fb_id
    WHERE
        f.parent = '1111'
    ORDER BY
        msg_info DESC;
    

    我们可以尝试为(parent, child, name, msg_info, ...) 上的friends 表添加索引。我不确定哪些其他列属于friends,但基本思想是在parent 上创建一个索引,以加快WHERE 子句的速度,并希望利用parent 列的低基数。然后,我们包含child 列以加快连接速度。我们还在 select 子句中包含所有其他列,让索引覆盖我们需要的其他列。

    CREATE INDEX idx ON friends (parent, child, name, msg_info, ...);
    

    【讨论】:

    • 如果这些索引列中的任何一个是TEXTCREATE 将失败。而且,当您超过 5 列时,“覆盖”的收益会递减。仅建议INDEX(parent)。如果msg_infofriends 中,则执行INDEX(parent, msg_info)
    • @RickJames 好的,但我不清楚 MySQL 是否会使用您建议的索引。
    猜你喜欢
    • 2015-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多