【问题标题】:How i can optimize my mysql query?如何优化我的 mysql 查询?
【发布时间】:2012-10-03 05:28:15
【问题描述】:
SELECT a.*, u.avatar, u.name, u.surname, u.username, COUNT(a.user1) AS cnt  
FROM user_actions a,users u,following f   
WHERE a.user1=u.user_id AND
a.user1=f.follower_id AND 
f.user_id=159 
GROUP BY a.user1, a.action, day(a.dt) 
ORDER BY a.id DESC 
LIMIT 7;

查询耗时 4.4909 秒

表 user_actions 的索引:

Action  Keyname     Type   Unique Packed Column    Cardinality Collation
Edit    PRIMARY     BTREE  Yes    No     id        516094      A        
Edit    user1       BTREE  No     No     user1     15639       A        
Edit    user2       BTREE  No     No     user2     36863       A        
Edit    action      BTREE  No     No     action    16          A        
Edit    dt          BTREE  No     No     dt        516094      A        
Edit    group_index BTREE  No     No     user1     20643       A        


EXPLAIN SELECT a . * , u.avatar, u.name, u.surname, u.username, COUNT( a.user1 ) AS cnt
FROM user_actions a, users u, following f
WHERE a.user1 = u.user_id
AND a.user1 = f.follower_id
AND f.user_id =159
GROUP BY a.user1, a.action, day( a.dt )
ORDER BY a.id DESC
LIMIT 7 

id select_type table type possible_keys key key_len ref rows 额外 1 SIMPLE f ref user_id,follower_id,for_actions for_actions 4 const 242 使用索引;使用临时的;使用文件排序 1 简单 参考 user1,group_index group_index 4 pictify_main.f.follower_id 25 1 SIMPLE u eq_ref PRIMARY PRIMARY 4 pictify_main.a.user1 1 使用哪里

【问题讨论】:

  • 您可以尝试在查询前添加 EXPLAIN 以获得详细分析。您可以在此处发布结果,以便我们查看问题所在。

标签: mysql sql


【解决方案1】:

由于格式化无法理解你的索引

但是以下索引可以提供帮助..

user_actions(user1)
following (user_id)
users(user_id)

否则,请发布解释计划。

【讨论】:

    【解决方案2】:

    非确定性分组: SQL 检索既不在聚合函数也不在 GROUP BY 表达式中的列,因此这些值在结果中将是不确定的。

    选择 *: 如果表的架构发生变化,选择所有带有 * 通配符的列将导致查询的含义和行为发生变化,并可能导致查询检索到过多的数据。

    不带 AS 关键字的别名 在列或表别名中显式使用 AS 关键字,例如“tbl AS alias”,比隐式别名(例如“tbl alias”)更具可读性。

    【讨论】:

      【解决方案3】:

      由于您正在寻找特定的“关注”用户 ID,因此我会对其进行一些反转...然后添加“STRAIGHT_JOIN”子句以告诉 MySQL 按明确列出的顺序执行

      确保索引 表索引 关注(User_ID,Follower_ID) 用户 (User_ID) User_Actions (User1,Action,Dt,ID)

      select STRAIGHT_JOIN
            UA.*,
            U.Avatar,
            U.Name,
            U.SurName,
            U.UserName,
            count(*) as UserActionsCount
         from
            Following F
               JOIN User_Actions UA
                  on F.Follower_ID = UA.User1
                  Join Users U
                     on UA.User1 = U.User_ID
         where
            F.User_ID = 159
         group by
            F.Follower_ID,
            UA.Action,
            Day( UA.Dt )
         order by
            UA.ID DESC
         limit 
            7
      

      【讨论】:

        【解决方案4】:

        使用连接而不是逗号分隔的FROM cluase:

        SELECT a.*, u.avatar, u.name, u.surname, u.username, COUNT(a.user1) AS cnt  
        FROM following f
        LEFT JOIN user_actions a ON a.user1 = f.follower_id
        LEFT JOIN users u ON u.user_id = a.user1
        WHERE f.user_id = 159 
        GROUP BY a.user1, a.action, day(a.dt) 
        ORDER BY a.id DESC 
        LIMIT 7;
        

        我选择在FROM 子句中使用following 表,因为您的搜索的关键部分是基于following.user_id。这应该会减少获取的行数,因为您要尽早缩小结果集的范围。

        我推荐LEFT JOIN,因为这将返回来自following 的行,即使它们与其他两个表中的任何条目都不匹配,这通常是您在这种查询中想要的结果。如果您只想要在所有 3 个表中都有数据的行,请改用 INNER JOIN

        【讨论】:

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