2015-07-01 48 views
1

我更新了freeradius的數據庫,現在有一個sql語句需要更多的時間才能執行30秒,而之前只需要0.5s執行。Mysql Index COLLATE utf8_unicode_ci

這是舊定​​義表:

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=3514770 DEFAULT CHARSET=latin1; 

CREATE TABLE `userinfo` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `username` varchar(128) DEFAULT NULL, 
    `firstname` varchar(200) DEFAULT NULL, 
    `lastname` varchar(200) DEFAULT NULL, 
    `email` varchar(200) DEFAULT NULL, 
    `department` varchar(200) DEFAULT NULL, 
    `company` varchar(200) DEFAULT NULL, 
    `workphone` varchar(200) DEFAULT NULL, 
    `homephone` varchar(200) DEFAULT NULL, 
    `mobilephone` varchar(200) DEFAULT NULL, 
    `address` varchar(200) DEFAULT NULL, 
    `city` varchar(200) DEFAULT NULL, 
    `state` varchar(200) DEFAULT NULL, 
    `country` varchar(100) DEFAULT NULL, 
    `zip` varchar(200) DEFAULT NULL, 
    `notes` varchar(200) DEFAULT NULL, 
    `changeuserinfo` varchar(128) DEFAULT NULL, 
    `portalloginpassword` varchar(128) DEFAULT '', 
    `enableportallogin` int(32) DEFAULT '0', 
    `creationdate` datetime DEFAULT '0000-00-00 00:00:00', 
    `creationby` varchar(128) DEFAULT NULL, 
    `updatedate` datetime DEFAULT '0000-00-00 00:00:00', 
    `updateby` varchar(128) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `username` (`username`), 
    KEY `company` (`company`) 
) ENGINE=MyISAM AUTO_INCREMENT=188493 DEFAULT CHARSET=latin1; 

這是新定義的表:比舊錶具有兩個字符集= LATIN1

CREATE TABLE `radacct` (
    `radacctid` bigint(21) NOT NULL AUTO_INCREMENT, 
    `acctsessionid` varchar(64) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 
    `acctuniqueid` varchar(32) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 
    `username` varchar(64) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 
    `groupname` varchar(64) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 
    `realm` varchar(64) COLLATE utf8_unicode_ci DEFAULT '', 
    `nasipaddress` varchar(15) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 
    `nasportid` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `nasporttype` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `acctstarttime` datetime DEFAULT NULL, 
    `acctstoptime` datetime DEFAULT NULL, 
    `acctsessiontime` int(12) DEFAULT NULL, 
    `acctauthentic` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `connectinfo_start` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `connectinfo_stop` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `acctinputoctets` bigint(20) DEFAULT NULL, 
    `acctoutputoctets` bigint(20) DEFAULT NULL, 
    `calledstationid` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 
    `callingstationid` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 
    `acctterminatecause` varchar(32) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 
    `servicetype` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `framedprotocol` varchar(32) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `framedipaddress` varchar(15) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 
    `acctstartdelay` int(12) DEFAULT NULL, 
    `acctstopdelay` int(12) DEFAULT NULL, 
    `xascendsessionsvrkey` varchar(10) COLLATE utf8_unicode_ci 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=MyISAM AUTO_INCREMENT=3519495 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

CREATE TABLE `userinfo` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `username` varchar(128) DEFAULT NULL, 
    `firstname` varchar(200) DEFAULT NULL, 
    `lastname` varchar(200) DEFAULT NULL, 
    `email` varchar(200) DEFAULT NULL, 
    `department` varchar(200) DEFAULT NULL, 
    `company` varchar(200) DEFAULT NULL, 
    `workphone` varchar(200) DEFAULT NULL, 
    `homephone` varchar(200) DEFAULT NULL, 
    `mobilephone` varchar(200) DEFAULT NULL, 
    `address` varchar(200) DEFAULT NULL, 
    `city` varchar(200) DEFAULT NULL, 
    `state` varchar(200) DEFAULT NULL, 
    `country` varchar(100) DEFAULT NULL, 
    `zip` varchar(200) DEFAULT NULL, 
    `notes` varchar(200) DEFAULT NULL, 
    `changeuserinfo` varchar(128) DEFAULT NULL, 
    `portalloginpassword` varchar(128) DEFAULT '', 
    `enableportallogin` int(32) DEFAULT '0', 
    `creationdate` datetime DEFAULT '0000-00-00 00:00:00', 
    `creationby` varchar(128) DEFAULT NULL, 
    `updatedate` datetime DEFAULT '0000-00-00 00:00:00', 
    `updateby` varchar(128) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `username` (`username`), 
    KEY `company` (`company`) 
) ENGINE=MyISAM AUTO_INCREMENT=188894 DEFAULT CHARSET=latin1; 

通知,同時通過定義新表具有不同的字符集和整理:CHARSET = utf8 COLLATE = utf8_unicode_ci和CHARSET = latin1。這應該是差異。

現在,這是我跑了一句:

select TIMESTAMPDIFF(SECOND,max(acctstarttime),now()) as segons,(department) as idClient,(userinfo.username) 
     from 
     (select radacct.username as id 
      from radacct,userinfo 
      where userinfo.company=98 
      and radacct.username = userinfo.username 
      group by userinfo.username 
      order by max(radacct.radacctid) desc limit 0,6) as tbl,radacct,userinfo 
     where radacct.username=tbl.id and radacct.username = userinfo.username 
     group by radacct.username 
     order by max(radacct.radacctid) desc; 

這是描述了舊錶 - 快速查詢(0.4秒):

id * select_type * table type possible_keys key key_len ref rows Extra * 
    1 PRIMARY <derived2> ALL {null} {null} {null} {null} 6 Using temporary; Using filesort 
    1 PRIMARY radacct ref username username 66 tbl.id 5 
    1 PRIMARY userinfo ref username username 131 radius.radacct.username 1 Using where 
    2 DERIVED radacct index username username 66 {null} 28768 Using index; Using temporary; Using filesort 
    2 DERIVED userinfo ref username,company username 131 radius.radacct.username 1 Using where 

這是描述的新表 - 慢查詢(30s):

id * select_type * table type possible_keys key key_len ref rows Extra * 
    1 PRIMARY <derived2> ALL {null} {null} {null} {null} 6 Using temporary; Using filesort 
    1 PRIMARY radacct ref username username 194 tbl.id 11 
    1 PRIMARY userinfo ALL {null} {null} {null} {null} 188911 Using where; Using join buffer 
    2 DERIVED userinfo ALL company {null} {null} {null} 188911 Using where; Using temporary; Using filesort 
    2 DERIVED radacct ref username username 194 func 11 Using where 

謝謝。

編輯:

我更改用戶信息的字符集:

alter table radius.userinfo convert to character set utf8 collate utf8_unicode_ci; 

現在新 - 慢速查詢在3秒內運行,但仍沒有那麼快的舊數據庫。

此外,我更改VARCHAR長度在兩個查詢是相同的,仍然不像索引OLD數據庫一樣索引。

ALTER TABLE radius.userinfo CHANGE username username VARCHAR(64); 

我只是運行子查詢推移緩慢:

select radacct.username as id 
     from radacct,userinfo 
     where userinfo.company=98 
     and radacct.username = userinfo.username 
     group by userinfo.username 
     order by max(radacct.radacctid) desc limit 0,6 

這是回答老 - 快速:

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE radacct index username username 66  37545 Using index; Using temporary; Using filesort 
1 SIMPLE userinfo ref username,company username 131 radius.radacct.username 1 Using where 

這是描述新 - 慢:

id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE radacct ALL username    56879 Using temporary; Using filesort 
1 SIMPLE userinfo ref company,username username 195 radius.radacct.username 1 Using where 

爲什麼沒有得到radacct .username索引?

編輯2:用新的COLLATION-CHARSET添加新的定義。

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

CREATE TABLE `userinfo` (
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `username` varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `firstname` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `lastname` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `email` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `department` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `company` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `workphone` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `homephone` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `mobilephone` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `address` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `city` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `state` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `country` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `zip` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `notes` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `changeuserinfo` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `portalloginpassword` varchar(128) COLLATE utf8_unicode_ci DEFAULT '', 
    `enableportallogin` int(32) DEFAULT '0', 
    `creationdate` datetime DEFAULT '0000-00-00 00:00:00', 
    `creationby` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `updatedate` datetime DEFAULT '0000-00-00 00:00:00', 
    `updateby` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `company` (`company`), 
    KEY `username` (`username`) 
) ENGINE=MyISAM AUTO_INCREMENT=191546 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;  

回答

0

我看到3個問題:

company = 98 
`company` varchar(200) DEFAULT NULL, 

如果它是那麼一些使用數字數據類型。

更換

​​

INDEX(company, username) 

但也許真正的問題是這樣的:

radacct.username = userinfo.username 

其中一個是latin1的,另一種是UTF8。

+0

嗨瑞克,謝謝,我用新信息編輯我的帖子。更改字符集使查詢運行更快。 INDEX(公司,用戶名)沒有任何區別。和公司= 98或公司= '98'一樣。現在varchar長度是一樣的,字符集是相同的,但沒有使用索引。 –

+0

再次運行_both_' SHOW CREATE TABLEs' - 驗證兩個'username'具有相同的'CHARACTER SET' _and_'COLLATION'。行動的確切順序可能會把事情搞砸。 –

+0

(假設你有足夠新的版本...)請至少爲「新的,慢的」提供'EXTEND FORMAT = JSON SELECT ...'。 –