MySQL使用date_format慢速分组

时间:2015-04-14 21:50:08

标签: mysql query-optimization

我有来自Daloradius的桌子:

{CREATE TABLE `radacct` (
  `radacctid` bigint(21) NOT NULL AUTO_INCREMENT,
  `acctsessionid` varchar(64) NOT NULL DEFAULT '',
  `acctuniqueid` varchar(32) NOT NULL DEFAULT '',
  `username` varchar(64) NOT NULL DEFAULT '',
  `groupname` varchar(64) NOT NULL DEFAULT '',
  `realm` varchar(64) DEFAULT '',
  `nasipaddress` varchar(15) NOT NULL DEFAULT '',
  `nasportid` varchar(15) DEFAULT NULL,
  `nasporttype` varchar(32) DEFAULT NULL,
  `acctstarttime` datetime DEFAULT NULL,
  `acctstoptime` datetime DEFAULT NULL,
  `acctsessiontime` int(12) DEFAULT NULL,
  `acctauthentic` varchar(32) DEFAULT NULL,
  `connectinfo_start` varchar(50) DEFAULT NULL,
  `connectinfo_stop` varchar(50) DEFAULT NULL,
  `acctinputoctets` bigint(20) DEFAULT NULL,
  `acctoutputoctets` bigint(20) DEFAULT NULL,
  `calledstationid` varchar(50) NOT NULL DEFAULT '',
  `callingstationid` varchar(50) NOT NULL DEFAULT '',
  `acctterminatecause` varchar(32) NOT NULL DEFAULT '',
  `servicetype` varchar(32) DEFAULT NULL,
  `framedprotocol` varchar(32) DEFAULT NULL,
  `framedipaddress` varchar(15) NOT NULL DEFAULT '',
  `acctstartdelay` int(12) DEFAULT NULL,
  `acctstopdelay` int(12) DEFAULT NULL,
  `xascendsessionsvrkey` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`radacctid`),
  KEY `username` (`username`),
  KEY `framedipaddress` (`framedipaddress`),
  KEY `acctsessionid` (`acctsessionid`),
  KEY `acctsessiontime` (`acctsessiontime`),
  KEY `acctuniqueid` (`acctuniqueid`),
  KEY `acctstarttime` (`acctstarttime`),
  KEY `acctstoptime` (`acctstoptime`),
  KEY `nasipaddress` (`nasipaddress`)
) ENGINE=InnoDB AUTO_INCREMENT=1797353 DEFAULT CHARSET=latin1;

}

有1797353行。

此查询延迟0.7秒:

select count(distinct(right(radacct.username,17))) as Navegant,0,0
            from radacct,userinfo
            where userinfo.company='98' and userinfo.username=radacct.username   

说明:

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  userinfo    ref username,company    company 203 const   4811    Using where
1   SIMPLE  radacct ref username    username    66  radius.userinfo.username    7   Using where; Using index   

但是当我添加date_format(acctstarttime,'%H')时,运行查询需要更多的tan 4:

select   date_format(acctstarttime,'%H') as AA,count(distinct(right(radacct.username,17))) as Navegant,0,0
            from radacct,userinfo
            where userinfo.company='98' and userinfo.username=radacct.username
            group by AA

说明:

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  userinfo    ref username,company    company 203 const   4811    Using where; Using temporary; Using filesort
1   SIMPLE  radacct ref username    username    66  radius.userinfo.username    7   Using where

如何更快地进行此查询?

2 个答案:

答案 0 :(得分:0)

我在Group By的表现方面遇到了很多问题。在某些情况下,我最终使用了子选择。这篇文章对我非常有帮助:

http://kccoder.com/mysql/join-group-by-performance/

基本上归结为采取这个: date_format(acctstarttime,'%H')为AA

从你的select语句中输入如下的子选择:

选择count(distinct(right(radacct.username,17)))为Navegant,0,0             来自radacct,userinfo,选择date_format(acctstarttime,'%H')作为来自some_table的AA
userinfo.company =' 98'和userinfo.username = radacct.username

我知道我的语法不正确,但它应该给你一般的想法。

希望这有帮助, 布赖恩

答案 1 :(得分:0)

where userinfo.company='98'

请求INDEX(company)

目前还不清楚为什么你需要两个表,因为相同的用户名都在这两个表中。看起来这对于第一个查询就足够了:

select count(distinct(right(username,17))) as Navegant,0,0
        from userinfo
        where company='98';

如果有效,那么这个复合指数会更好,因为它涵盖了INDEX(company, username)

你的第二个查询将受益于INDEX,后者更好,因为它可以是"使用索引"至少对userinfo