在mysql查询的表上创建索引,涉及join,group / order-by,union等

时间:2016-06-23 07:35:54

标签: mysql sql

下面是mysql进程列表中具有10个"copying to tmp table"状态的慢查询的解释输出。

explain SELECT distinct
    (radgroupreply.groupname),
    count(distinct (radusergroup.username)) AS users
FROM
    radgroupreply
        LEFT JOIN
    radusergroup ON radgroupreply.groupname = radusergroup.groupname
WHERE
    (radgroupreply.groupname NOT LIKE 'FB-%' AND radgroupreply.groupname NOT LIKE '%Dropped%')
GROUP BY radgroupreply.groupname 
UNION SELECT distinct
    (radgroupcheck.groupname),
    count(distinct (radusergroup.username))
FROM
    radgroupcheck
        LEFT JOIN
    radusergroup ON radgroupcheck.groupname = radusergroup.groupname
WHERE
    (radgroupcheck.groupname NOT LIKE 'FB-%' AND radgroupcheck.groupname NOT LIKE '%Dropped%')
GROUP BY radgroupcheck.groupname
ORDER BY groupname asc;

+----+--------------+---------------+------+---------------+------+---------+------+-------+----------------------------------------------+
| id | select_type  | table         | type | possible_keys | key  | key_len | ref  | rows  | Extra                                        |
+----+--------------+---------------+------+---------------+------+---------+------+-------+----------------------------------------------+
|  1 | PRIMARY      | radgroupreply | ALL  | NULL          | NULL | NULL    | NULL |   456 | Using where; Using temporary; Using filesort |
|  1 | PRIMARY      | radusergroup  | ALL  | NULL          | NULL | NULL    | NULL | 10261 |                                              |
|  2 | UNION        | radgroupcheck | ALL  | NULL          | NULL | NULL    | NULL |   167 | Using where; Using temporary; Using filesort |
|  2 | UNION        | radusergroup  | ALL  | NULL          | NULL | NULL    | NULL | 10261 |                                              |
|NULL| UNION RESULT | <union1,2>    | ALL  | NULL          | NULL | NULL    | NULL |  NULL | Using filesort                               |
+----+--------------+---------------+------+---------------+------+---------+------+-------+----------------------------------------------+
5 rows in set (0.00 sec)

我无法理解这个查询以创建复合/单索引并进行优化,因为它有多个连接,分组和类似操作。

1 个答案:

答案 0 :(得分:2)

以下是三个开始的观察结果。

  1. select distinct是不必要的(group by负责处理)。
  2. left join是不必要的(where子句将它们转换为内连接。)
  3. UNION应该是UNION ALL。我怀疑你是否真的想要消除重复的开销。
  4. 因此,您可以将查询编写为:

    SELECT rr.groupname, count(distinct rg.username) AS users  
    FROM radgroupreply rr JOIN
         radusergroup rg
         ON rr.groupname = rg.groupname                                                  
    WHERE rr.groupname NOT LIKE 'FB-%' AND rr.groupname NOT LIKE '%Dropped%'
    GROUP BY rr.groupname 
    UNION ALL
    SELECT rc.groupname, count(rg.username)
    FROM radgroupcheck rc JOIN
         radusergroup rg
         ON rc.groupname = rg.groupname                                 
    WHERE rc.groupname NOT LIKE 'FB-%' AND rc.groupname NOT LIKE '%Dropped%'
    GROUP BY rc.groupname
    ORDER BY groupname asc;
    

    此查询可以利用radusergroup(groupname)上的索引。我猜测会使用rc(radusergroup)上的索引。

    如果没有必要,我还建议您删除DISTINCT中的COUNT(DISTINCT)