【问题标题】:How to improve a MySQL join query speed?如何提高 MySQL 连接查询速度?
【发布时间】:2021-12-24 17:54:51
【问题描述】:

表名称:帐户

AccountId RegDate Name password
A 20211101 Rosa 1234
B 20211102 Daisy 2345
C 20211103 Holly 3456

表名:account_history

AccountId LoginTime Os browser
A 202111011303 mac safari
B 202111011406 window chrome
C 202111012507 android chrome
A 202111051903 mac safari
B 202111051806 window chrome
C 202111052707 android chrome
A 202111061603 mac safari
B 202111061406 window chrome
C 202111072007 android chrome
A 202111087303 mac safari
B 202111088406 window chrome
C 202111089507 android chrome

我想要的结果。

AccountId RegDate LatestLoginTime os
A 20211101 2021202111087303101 202111087303
B 20211102 202111088406 202111088406
C 20211103 202111089507 android

我用过

SELECT a.AccountId,a.RegDate,b.LatestLoginTime,b.Os 
FROM account a 
LEFT JOIN (SELECT MAX(LoginTime) as LatestLoginTime,AccountId,Os
           FROM accounthistory GROUP BY AccountId) b
ON a.AccountId = b.AccountId 

但是这个查询太慢了。如何快速获得我想要的数据?

【问题讨论】:

  • 之前尝试使用关键字EXPLAIN 运行查询,以便数据库解释查询是如何执行的,并有助于找到优化它的方法。你可以阅读更多here
  • 添加show create table 语句显示表索引
  • 在以下 SO 问题中列出了大约 6 种不同的解决方案:stackoverflow.com/questions/7745609/… 您也可以尝试这些解决方案。
  • 您可以尝试使用选择数据创建另一个表。您的表 account_history 它是源日志,如果您用于特定网格,则需要创建 account_last_activity 其中与表 account_history 相同的列。
  • 就像是INSERT INTO t1 (a,b,c) VALUES (1,2,3) ON DUPLICATE KEY UPDATE c=c+1; docs

标签: mysql mariadb query-optimization


【解决方案1】:
   SELECT h.AccountId,
          a.RegDate,
          MAX(h.LoginTime) AS LatestLoginTime,
          h.Os
     FROM Account AS a
LEFT JOIN AccountHistory AS h USING (AccountId)
 GROUP BY h.AccountId, a.RegDate, h.Os

两个表中的 AccountId 索引和 AccountHistory 中的 LoginTime 索引。

sqlfiddle

【讨论】:

    【解决方案2】:

    这两个索引可能会有所帮助:

    account:  INDEX(AccountId,  RegDate)
    accounthistory:  INDEX(AccountId,  LatestLoginTime, OS)
    

    但也有问题:

    • Os 是否依赖于AccountId? (参见:only_full_group_by)
    • 为什么是LEFT

    根据您的回答,可能会有更好的方法来制定查询。

    一个帐户可以有两个不同的操作系统值吗?

    考虑以下几点:

    SELECT  a.AccountId,
            b.OS,
            a.RegDate,
            b.LatestLoginTime
        FROM (
            SELECT  MAX(LoginTime) as LatestLoginTime,
                    AccountId, OS
                FROM  accounthistory
                GROUP BY  AccountId, OS
             ) AS b  
        JOIN account a  ON a.AccountId = b.AccountId 
    

    如果您只希望每个帐户一行,以及最后一次登录的操作系统,那么这是一个更复杂的查询——搜索“groupwise-maximum”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-09
      • 2021-11-17
      • 2016-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-31
      • 1970-01-01
      相关资源
      最近更新 更多