mysql查询耗时超过30秒

时间:2016-08-07 07:55:04

标签: mysql sql query-optimization

下面是my-sql命令行上“show full processlist”的输出。此查询计算指定时间段内的用户总上载和下载带宽。 (数据库来自freeradius)。如何更快地进行查询? [记忆:150G,处理器:8 centos 6.8]

15260415|radiusremote|panel.example.com:57526|radius|Query|35|Copying to tmp table  

SELECT  sum(acctinputoctets) as upload,sum(acctoutputoctets) as download
    FROM  radacct a
    INNER JOIN  
        ( SELECT  acctuniqueid, MIN( radacctid ) radacctid
            FROM  radacct
            WHERE  username='nyjohan'
              and  acctstarttime between '2016-01-15 13:50:05'
                                     AND '2016-08-07 13:16:36'
            GROUP BY  acctuniqueid
        ) b  ON a.acctuniqueid = b.acctuniqueid
           AND  a.radacctid = b.radacctid 

表上创建了索引,下面是表

上的索引输出
mysql> show index from radacct;
+---------+------------+-----------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+
| Table   | Non_unique | Key_name        | Seq_in_index | Column_name     | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+---------+------------+-----------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+
| radacct |          0 | PRIMARY         |            1 | radacctid       | A         |   161791738 |     NULL | NULL   |      | BTREE      |         |
| radacct |          1 | username        |            1 | username        | A         |          15 |     NULL | NULL   |      | BTREE      |         |
| radacct |          1 | framedipaddress |            1 | framedipaddress | A         |      458333 |     NULL | NULL   |      | BTREE      |         |
| radacct |          1 | acctsessionid   |            1 | acctsessionid   | A         |   161791738 |     NULL | NULL   |      | BTREE      |         |
| radacct |          1 | acctsessiontime |            1 | acctsessiontime | A         |       46332 |     NULL | NULL   | YES  | BTREE      |         |
| radacct |          1 | acctuniqueid    |            1 | acctuniqueid    | A         |   161791738 |     NULL | NULL   |      | BTREE      |         |
| radacct |          1 | acctstarttime   |            1 | acctstarttime   | A         |    40447934 |     NULL | NULL   | YES  | BTREE      |         |
| radacct |          1 | acctstoptime    |            1 | acctstoptime    | A         |    80895869 |     NULL | NULL   | YES  | BTREE      |         |
| radacct |          1 | nasipaddress    |            1 | nasipaddress    | A         |          15 |     NULL | NULL   |      | BTREE      |         |
+---------+------------+-----------------+--------------+-----------------+-----------+-------------+----------+--------+------+------------+---------+

表的架构

mysql> describe radacct;
+----------------------+-------------+------+-----+---------+----------------+
| Field                | Type        | Null | Key | Default | Extra          |
+----------------------+-------------+------+-----+---------+----------------+
| radacctid            | bigint(21)  | NO   | PRI | NULL    | auto_increment |
| acctsessionid        | varchar(32) | NO   | MUL |         |                |
| acctuniqueid         | varchar(32) | NO   | MUL |         |                |
| username             | varchar(64) | NO   | MUL |         |                |
| groupname            | varchar(64) | NO   |     |         |                |
| realm                | varchar(64) | YES  |     |         |                |
| nasipaddress         | varchar(15) | NO   | MUL |         |                |
| nasportid            | varchar(15) | YES  |     | NULL    |                |
| nasporttype          | varchar(32) | YES  |     | NULL    |                |
| acctstarttime        | datetime    | YES  | MUL | NULL    |                |
| acctstoptime         | datetime    | YES  | MUL | NULL    |                |
| acctsessiontime      | int(12)     | YES  | MUL | NULL    |                |
| acctauthentic        | varchar(32) | YES  |     | NULL    |                |
| connectinfo_start    | varchar(50) | YES  |     | NULL    |                |
| connectinfo_stop     | varchar(50) | YES  |     | NULL    |                |
| acctinputoctets      | bigint(20)  | YES  |     | NULL    |                |
| acctoutputoctets     | bigint(20)  | YES  |     | NULL    |                |
| calledstationid      | varchar(50) | NO   |     |         |                |
| callingstationid     | varchar(50) | NO   |     |         |                |
| acctterminatecause   | varchar(32) | NO   |     |         |                |
| servicetype          | varchar(32) | YES  |     | NULL    |                |
| framedprotocol       | varchar(32) | YES  |     | NULL    |                |
| framedipaddress      | varchar(15) | NO   | MUL |         |                |
| acctstartdelay       | int(12)     | YES  |     | NULL    |                |
| acctstopdelay        | int(12)     | YES  |     | NULL    |                |
| xascendsessionsvrkey | varchar(10) | YES  |     | NULL    |                |
+----------------------+-------------+------+-----+---------+----------------+

解释输出: -

explain SELECT sum(acctinputoctets) as upload,sum(acctoutputoctets) as download
FROM radacct a
INNER JOIN (
SELECT acctuniqueid, MIN( radacctid ) radacctid
FROM radacct
WHERE username='dave137' and acctstarttime between '2016-08-03 00:00:00' and '2016-08-07 14:47:54' GROUP BY acctuniqueid
)b ON a.acctuniqueid = b.acctuniqueid
AND a.radacctid = b.radacctid ;

+----+-------------+------------+--------+------------------------+----------+---------+-------------+-------+----------------------------------------------+
| id | select_type | table      | type   | possible_keys          | key      | key_len | ref         | rows  | Extra                                        |
+----+-------------+------------+--------+------------------------+----------+---------+-------------+-------+----------------------------------------------+
|  1 | PRIMARY     | <derived2> | ALL    | NULL                   | NULL     | NULL    | NULL        |    10 |                                              |
|  1 | PRIMARY     | a          | eq_ref | PRIMARY,acctuniqueid   | PRIMARY  | 8       | b.radacctid |     1 | Using where                                  |
|  2 | DERIVED     | radacct    | ref    | username,acctstarttime | username | 66      |             | 10164 | Using where; Using temporary; Using filesort |
+----+-------------+------------+--------+------------------------+----------+---------+-------------+-------+----------------------------------------------+
3 rows in set (9.91 sec)

2 个答案:

答案 0 :(得分:3)

对于此查询:

SELECT sum(acctinputoctets) as upload,sum(acctoutputoctets) as download
FROM radacct a INNER JOIN
     (SELECT acctuniqueid, MIN( radacctid ) as radacctid
      FROM radacct
      WHERE username = 'dave137' and acctstarttime between '2016-08-03 00:00:00' and '2016-08-07 14:47:54'
      GROUP BY acctuniqueid
     ) b
     ON a.acctuniqueid = b.acctuniqueid AND a.radacctid = b.radacctid ;

我建议使用两个索引,一个已经存在:radacct(radacctid)radacct(username, acctstarttime, acctuniqueid)

此外,我会将ON子句简化为:

     ON a.radacctid = b.radacctid ;

radacctid是唯一的,因此不需要其他条件。

答案 1 :(得分:1)

在子查询中使用JOIN会降低查询速度,无论索引如何。从我所看到的,这应该做同样的事情而不需要进行子连接:

SELECT acctinputoctets as upload, acctoutputoctets as download
FROM radacct a 
WHERE username = 'dave137' 
and acctstarttime between '2016-08-03 00:00:00' and '2016-08-07 14:47:54'
ORDER BY radacctid 
LIMIT 1