使用Count和2个表的MYSQL查询优化问题

时间:2020-05-24 15:59:48

标签: mysql join group-by count

我有2张桌子 hudges hentry

hjudges表显示每个事件ID,类别,时间,日期

jeid (primary) | jcategory | jtimeofday | jedate

    101 |beginner    |AM|2020-01-01|
    101 |intermediate|AM|2020-01-01|
    101 |advanced    |AM|2020-01-01|
    102 |beginner    |AM|2020-01-05|
    102 |intermediate|AM|2020-01-05|
    102 |advanced    |AM|2020-01-05|

hentry表显示“输入”该事件的用户。 (为了简化起见,省略了一些信息)

hentryid (primary)|heid | hcategory | htimeofday | hedate | huserid | hstatus | hedtime

1| 101 | beginner     |AM|2020-01-01| 5 |active | 2019-12-05 12:00:00
2| 101 | intermediate |AM|2020-01-01| 5 |active | 2019-12-05 12:00:00
3| 101 | beginner     |AM|2020-01-01| 6 |active | 2019-12-05 12:00:00
4| 101 | intermediate |AM|2020-01-01| 6 |active | 2019-12-05 12:00:00

由于事件有限,当人们输入时,我要对条目进行计数。

以下查询有效,但是非常慢。这需要9秒钟或更长时间。

select 
ei.jcategory as jcategory, 
ei.jtimeofday  as jtimeofday , 
ei.jedate as jedate,
(select count(*) from hentry  e where e.heid =ei.jeid  and e.hcategory = ei.jcategory and ei.jedate = e.hedate and ei.jtimeofday = e.htimeofday 
and (((e.hstatus = 'pending' or e.hstatus = 'npending') and e.hedtime <= DATE_SUB(NOW(), INTERVAL 500000 MICROSECOND) and e.huserid <> '5' ) OR (e.hstatus = 'active')) ) as count 
from hjudges  ei where ei.jeid  = '101' 
group by ei.jedate, ei.jtimeofday, ei.jcategory

下面是结果,但是可能要花很长时间,具体取决于查询。

jcategory   |jtimeofday|jedate    | count    
 beginner   |AM        |2020-01-01| 2
intermediate|AM        |2020-01-01| 2
advanced    |AM        |2020-01-01| 0

我能够创建一些替代的联接查询,但是要么无法正确计数,要么对于高级级别不显示0。因为条目表中没有任何条目。

需要帮助。

1 个答案:

答案 0 :(得分:1)

您是否可以尝试联接表,而不是像这样进行子查询:

SELECT ei.jcategory AS jcategory,
       ei.jtimeofday AS jtimeofday ,
       ei.jedate AS jedate,
       count(*)
FROM hjudges ei
LEFT JOIN hentry e on e.heid =ei.jeid
    AND e.hcategory = ei.jcategory
    AND ei.jedate = e.hedate
    AND ei.jtimeofday = e.htimeofday
    AND (e.hstatus = 'active'
        OR
        (e.hstatus in ('pending', 'npending') AND e.hedtime <= DATE_SUB(NOW(), INTERVAL 500000 MICROSECOND) AND e.huserid <> '5'))
    AND ei.jeid = '101'
GROUP BY ei.jedate,
         ei.jtimeofday,
         ei.jcategory

还要在hstatus,hedtime和huserid上创建索引,然后运行查询。还有其他解决方法,例如将查询分为两个。如果查询很短,我会在评论中添加它。

提供MySQL提示以使用您选择的索引

当您执行建议的explain select...之类的nbk时,MySQL会告诉您所使用的索引。您可以为查询提供提示,以使用与其选择的索引不同的索引。为此,请参见https://dev.mysql.com/doc/refman/5.7/en/index-hints.html

拆分查询

您可以将查询分为2个-一个的hstatus为active状态,另一个为其他hstatuses。

select jcategory, jtimeofday, jedate, sum(totals)
from
(
    SELECT ei.jcategory AS jcategory,
           ei.jtimeofday AS jtimeofday ,
           ei.jedate AS jedate,
           count(*) as totals
    FROM hjudges ei
    LEFT JOIN hentry e on e.heid =ei.jeid
        AND e.hcategory = ei.jcategory
        AND ei.jedate = e.hedate
        AND ei.jtimeofday = e.htimeofday
        AND e.hstatus = 'active'
        AND ei.jeid = '101'
    GROUP BY ei.jedate,
             ei.jtimeofday,
             ei.jcategory

    union all

    SELECT ei.jcategory AS jcategory,
           ei.jtimeofday AS jtimeofday ,
           ei.jedate AS jedate,
           count(*) as totals
    FROM hjudges ei
    LEFT JOIN hentry e on e.heid =ei.jeid
        AND e.hcategory = ei.jcategory
        AND ei.jedate = e.hedate
        AND ei.jtimeofday = e.htimeofday
        AND e.hstatus in ('pending', 'npending')
        AND e.hedtime <= DATE_SUB(NOW(), INTERVAL 500000 MICROSECOND)
        AND e.huserid <> '5'
        AND ei.jeid = '101'
    GROUP BY ei.jedate,
             ei.jtimeofday,
             ei.jcategory
) x
group by jcategory, jtimeofday, jedate

这将使您可以注释掉两个查询中的一个,以分别研究性能,并找出哪个是瓶颈以及为什么,以及为使其运行更快而设置什么样的索引。