2014-03-26 71 views
0

表:如何通過優化MySQL的組

CREATE TABLE IF NOT EXISTS `l_not_200_page` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    `server` tinyint(3) unsigned NOT NULL, 
    `domain` tinyint(3) unsigned NOT NULL, 
    `page` varchar(128) NOT NULL, 
    `query_string` varchar(384) NOT NULL, 
    `status` smallint(5) unsigned NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `idx_time_domain_status_page` (`time`,`domain`,`status`,`page`), 
    KEY `page` (`page`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; 

解釋:

EXPLAIN SELECT * 
FROM `l_not_200_page` 
WHERE TIME 
BETWEEN TIMESTAMP( '2014-03-25') 
AND TIMESTAMP( '2014-03-25 23:59:59') 
AND domain =1 
AND STATUS = 404 
GROUP BY PAGE 

1 
SIMPLE 
l_not_200_page 
range 
idx_time_domain_status_page 
idx_time_domain_status_page 
7 
NULL 
1 
Using where; Using temporary; Using filesort 

它的速度很慢,如何優化?

SQL: 選擇頁面,COUNT(*)AS CNT FROM l_not_200_page ,時間 之間的時間戳( '2014年3月26日12:00:00') 和時間戳(「2014年3月26日12 :30:00' ) 和域= 1 AND STATUS = 499 GROUP BY PAGE ORDER BY CNT DESC LIMIT 100

約900瓦特每日量數據的

回答

1

更改索引:

create index `idx_domain_status_time_page` on l_not_200_page(`domain`, `status`, `time`, `page`) 

當MySQL使用索引爲一個where子句,最好索引具有相等比較所有字段後面跟着一個與不等式,如between。使用time作爲第一個元素,它不使用domainstatus的索引(當然,它使用索引掃描而不是直接查找)。

進一步優化,就可以得到每頁選擇一行擺脫group by的:

SELECT lp.* FROM l_not_200_page lp WHERE TIME BETWEEN TIMESTAMP( '2014-03-25') AND TIMESTAMP( '2014-03-25 23:59:59') AND 
     domain = 1 AND STATUS = 404 AND 
     NOT EXISTS (select 1 
        from l_not_200_page lp2 
        where lp2.page = lp.page and 
         lp2.domain = 1 and lp2.status = 404 and 
         lp2.TIME BETWEEN TIMESTAMP('2014-03-25) AND TIMESTAMP('2014-03-25 23:59:59') AND 
         lp2.id > lp.id 
       ) 

爲此,在(page, domain, status, time)一個附加的索引會有所幫助。