2016-06-23 13 views
3

mysql processlistに10の"copying to tmp table"という状態を持つ低速クエリの説明出力を以下に示します。join、group/order-by、unionなどを含むmysqlクエリ用のテーブルのインデックスを作成する

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) 

Iは、化合物/単一のインデックスを作成し、それが複数で、操作によって等のグループに参加しているので、最適化するために、このクエリのまわりで私の頭を取得傾けます。

+1

'DISTINCT'は' SELECT DISTINCT'の一部であり、(列上の)関数ではありません。これらのかっこは完全に冗長です。 (すなわち、select distinct(c1)、c2、...は、select distinct c1、c2、...と同じです。これは、select distinct c1、(c2)、...と同じです。 ) – jarlh

+0

radusergroup.groupnameにインデックスがありますか? –

+0

radusergroup.groupname、radusergroup.usernameにはインデックスが必要なので、インデックスからカウントを取得することもできます。 –

答えて

2

ここに3つの観察があります。

  1. select distinctは不要です(group byが対応しています)。
  2. left joinは不要です(where句は内部結合に変換します)。
  3. UNIONはおそらくUNION ALLです。私はあなたが本当に重複を取り除くオーバーヘッドを被りたいとは思わない。このクエリは、radusergroup(groupname)のインデックスを利用することができます

    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; 
    

だから、あなたは、としてクエリを記述することができます。私はrc(radusergroup)のインデックスを使用していると推測しています。

COUNT(DISTINCT)DISTINCTを削除することもお勧めします。

関連する問題