繁体   English   中英

我如何优化我的MySQL查询?

[英]How i can optimize my mysql query?

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表的类型possible_keys键key_len参考行额外1 SIMPLE f ref user_id,follower_id,for_actions for_actions 4 const 242使用索引; 使用临时; 使用filesort 1 SIMPLE a ref用户1,group_index group_index 4 pictify_main.f.follower_id 25 1 SIMPLE u eq_ref PRIMARY PRIMARY 4 pictify_main.a.user1 1在哪里使用

由于格式原因,无法理解您的索引

但是,以下索引可能会有所帮助。

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

否则建议,请发布解释计划。

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

SELECT *:如果表的模式更改,则选择所有带有*通配符的列将导致查询的含义和行为发生变化,并可能导致查询检索太多数据。

使用AS关键字的别名在列或表别名(例如“ tbl AS别名”)中明确使用AS关键字比诸如“ tbl别名”之类的隐式别名更具可读性。

由于您正在寻找特定的“以下”用户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

使用联接而不是逗号分隔的FROM分隔符:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM