如何优化分组?

时间:2018-12-03 14:32:48

标签: mysql sql optimization preforking

这是我的查询:

EXPLAIN SELECT Count(1), 
       user_id, 
       type 
FROM   (SELECT e.user_id, 
               e.type, 
               Max(r.date_time) last_seen, 
               e.date_time      event_time 
        FROM   events e 
               JOIN requests r 
                 ON e.user_id = r.user_id 
                    AND e.type IN( 3, 5, 6 ) 
        GROUP  BY e.user_id, 
                  e.date_time, 
                  e.type 
        HAVING last_seen < event_time) x 
GROUP  BY user_id, 
          type

这也是EXPLAIN的结果:

enter image description here

这也是该子查询(xEXPLAIN的结果:

enter image description here

看到了吗?非常理想。所以问题在这里分组。知道如何使查询更好吗?


编辑:我们需要两个表:

  1. requests表-将针对每个用户请求在其中插入新行。因此,最后一次(最大)决定了用户最后一次访问我们网站的时间。

  2. events表-对于每个答案和注释,将在其中插入新行。

我们正在谈论一个Q / A网站。我们要做的就是“向上次在我们网站上在线后获得新评论/答案的用户发送电子邮件”。

4 个答案:

答案 0 :(得分:2)

您需要在表上使用适当的索引以匹配WHERE子句和Order by来帮助优化。

table      index on...
events     ( type, user_id, date_time )
requests   ( user_id, date_time ) 

我什至建议对查询稍作调整。
更改

AND e.type IN( 3, 5, 6 ) 

WHERE e.type IN( 3, 5, 6 ) 

因为“ e.Type”基于查询的主表,与实际连接到请求表无关。该联接应代表实际的列,以在表之间进行限定。

SUGGESTION帖子编辑到问题。我可能会提供其他选择。在您的用户表中为“ lastRequest”日期/时间字段添加一列。然后,每当为该用户输入请求时,请更新用户表中的字段。您无需保留子查询max()即可确定何时。这可能会将查询简化为类似...随着请求表的增大,查询时间也将随之增大。通过直接在用户表ONCE上查找已知的最新请求,您可以找到答案。查询1万个用户或200万个请求...您可以选择:)

select 
      u.user_id,
      e.type,
      count(*) CountPerType,
      min( e.date_time ) firstEventDateAfterUsersLastRequest
   from
      user u
         join events e 
            on u.user_id = e.user_id
           AND e.type in ( 3, 5, 6 )
           AND e.date_time > u.lastRequest
   group by
      u.user_id,
      e.type

因此,您的联接已经具有每个用户的基本日期/时间,您可以仅在该人最后一次请求某项之后查找这些记录(因此进行跟踪)。

然后,要在用户表中准备新列,您可以使用每个用户的max(request.date_time)进行更新。

如果某个人在11月27日之前是活跃的,并且在3种不同的事件类型之后有5个响应,那么在11月27日之前您仍然可以得到该人,但是其他人可能会使用新的或旧的“ latestRequest”日期。

只是一个可选的想法。

答案 1 :(得分:1)

step 2

npm run detox-ios-test

答案 2 :(得分:1)

我会这样重写查询:

select user_id, type, count(*)
from (select e.user_id, e.type, e.date_time, 
             (select max(r.date_time)
              from requests r
              where r.user_id = e.user_id
              ) as last_seen 
       from events e 
       where e.type  in ( 3, 5, 6 ) 
      ) er
where last_seen < date_time
group by user_id, type;

然后,我要确保requests(user_id, date_time)events(type, user_id, date_time)上有索引。

答案 3 :(得分:0)

看看这是否得到“正确”的答案:

SELECT  COUNT(DISTINCT(e.date_time),
        e.user_id, e.type
    FROM  events e
    JOIN  requests r  ON  e.user_id = r.user_id
                     AND  e.type IN( 3, 5, 6 )
    GROUP BY  e.user_id, e.type
    HAVING  MAX(r.date_time) < e.event_time

索引:

e:  INDEX(type)   -- may be useful (depends on cardinality)
r:  INDEX(user_id, date_time)  -- in this order