我正在運行查詢,通過日期範圍搜索連接多個表,並試圖找出如何進一步優化它。mysql - 避免由於索引無效造成的filesort ..?
SELECT ACC.name AS account_name, CAMP.account_id AS account_id,CAMP.name AS campaign_name,CAMP.id AS campaign_id,ADG.id AS adgroup_id,ADG.name AS adgroup_name,KW.text AS keyword_name,
SUM(SPENT.billed_clicks) AS billed_clicks,KW.id AS keyword_id,KW.status_id AS status_id FROM account ACC, campaign CAMP,adgroup ADG,adgroup_keyword KW INNER JOIN keyword_spent SPENT
ON KW.id = SPENT.keyword_id WHERE summary_date >= '2012-03-01' AND summary_date <= '2012-03-04' AND KW.adgroup_id = ADG.id AND ADG.campaign_id = CAMP.id AND CAMP.account_id = ACC.id
GROUP BY keyword_id
關於這個EXPLAIN產生下面 - 它
+----+-------------+-------+--------+----------------------------+--------------+---------+---------------------------------+--------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+----------------------------+--------------+---------+---------------------------------+--------+----------------------------------------------+
| 1 | SIMPLE | SPENT | range | summary_date | summary_date | 3 | NULL | 752191 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | KW | eq_ref | PRIMARY,FK1948D0E6ED3A5544 | PRIMARY | 8 | clicksummarydb.SPENT.keyword_id | 1 | |
| 1 | SIMPLE | ADG | eq_ref | PRIMARY,FKBBC2083C29112FD0 | PRIMARY | 8 | advertisedb.KW.adgroup_id | 1 | |
| 1 | SIMPLE | CAMP | eq_ref | PRIMARY,FKF7A90110246F33C4 | PRIMARY | 8 | advertisedb.ADG.campaign_id | 1 | |
| 1 | SIMPLE | ACC | eq_ref | PRIMARY | PRIMARY | 8 | advertisedb.CAMP.account_id | 1 | |
+----+-------------+-------+--------+----------------------------+--------------+---------+---------------------------------+--------+----------------------------------------------+
的keyword_spent表包含了超過150萬行,這裏是展示創建表
| keyword_spent | CREATE TABLE `keyword_spent` (
`id` bigint(20) NOT NULL auto_increment,
`summary_date` date NOT NULL,
`adgroup_id` bigint(20) NOT NULL,
`keyword_id` bigint(20) NOT NULL,
`billed_clicks` int(11) default NULL,
`un_billed_clicks` int(11) default NULL,
`spent` decimal(20,5) default NULL,
`last_click_recno` bigint(20) default NULL,
`campaign_id` bigint(20) NOT NULL,
`account_id` bigint(20) NOT NULL,
`total_convs` bigint(20) unsigned default '0',
PRIMARY KEY (`id`),
UNIQUE KEY `keyword_spent_uniq` (`summary_date`,`adgroup_id`,`keyword_id`),
KEY `idx_account_id` (`account_id`),
KEY `idx_kw_id` (`keyword_id`),
KEY `adgroup_id` (`adgroup_id`),
KEY `campaign_id` (`campaign_id`),
KEY `summary_date` (`summary_date`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
我不不明白爲什麼在該日期範圍內沒有超過100,000條記錄時,有近750,000行正在被掃描。
此外,它爲什麼做一個filesort而不是使用索引。 ?
要做的第一件事就是擺脫A,B,C的東西,並對每一個使用inner join,所以where子句就在summary_date上。 – 2012-07-06 17:50:49
@Tony:我同意。我更喜歡使用逗號樣式join sytnax的'JOIN ... ON'語法。順便說一下...'summary_date'上的謂詞可以很容易地包含在JOIN的ON子句中,不必位於WHERE子句中,根本就不需要任何WHERE子句。 – spencer7593 2012-07-06 18:09:08
我重新安排了這兩個建議的查詢。只是好奇,除了看起來更清潔,它是否會給予任何性能提升。 – 2012-07-06 18:15:00