我有一個查詢,其目的是爲了生成不同時期(按月,按季度,按年份等)從網站下載多少音樂作品(曲目)的統計數據。該查詢在表entityusage
,entityusage_file
和track
上運行。如何優化一個依賴於COUNT和GROUP BY的查詢?
要獲得下載的數量屬於一個特定的專輯我會做下面的查詢曲目:
select
date_format(eu.updated, '%Y-%m-%d') as p, count(eu.id) as c
from entityusage as eu
inner join entityusage_file as euf
ON euf.entityusage_id = eu.id
inner join track as t
ON t.id = euf.track_id
where
t.album_id = '0054a47e-b594-407b-86df-3be078b4e7b7'
and entitytype = 't'
and action = 1
group by date_format(eu.updated, '%Y%m%d')
我需要設置entitytype = 't'
爲entityusage可以容納其他實體的下載,以及(如果entitytype = 'a'
那麼整個專輯將被下載,然後entityusage_file
將保存專輯在下載時被「翻譯」的所有曲目)。
此查詢需要40 - 50秒。我一直試圖優化這個查詢一段時間,但我覺得我正在接近這個錯誤的方式。
這是必須運行以生成報告的4個類似查詢中的一個。報告最好能夠在用戶等待時完成。現在,我看着3-4分鐘。等待很長時間。
此查詢是否可以通過索引進一步優化,還是需要採取另一種方法才能完成此項工作?
CREATE TABLE `entityusage` (
`id` char(36) NOT NULL,
`title` varchar(255) DEFAULT NULL,
`entitytype` varchar(5) NOT NULL,
`entityid` char(36) NOT NULL,
`externaluser` int(10) NOT NULL,
`action` tinyint(1) NOT NULL,
`updated` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `e` (`entityid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `entityusage_file` (
`id` char(36) NOT NULL,
`entityusage_id` char(36) NOT NULL,
`track_id` char(36) NOT NULL,
`file_id` char(36) NOT NULL,
`type` varchar(3) NOT NULL,
`quality` int(1) NOT NULL,
`size` int(20) NOT NULL,
`updated` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `file_id` (`file_id`),
KEY `entityusage_id` (`entityusage_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `track` (
`id` char(36) NOT NULL,
`album_id` char(36) NOT NULL,
`number` int(3) NOT NULL DEFAULT '0',
`title` varchar(255) DEFAULT NULL,
`updated` datetime NOT NULL DEFAULT '2000-01-01 00:00:00',
PRIMARY KEY (`id`),
KEY `album` (`album_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC;
上查詢的EXPLAIN
給我下面的:
+------+-------------+-------+--------+----------------+----------------+---------+------------------------------+---------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+--------+----------------+----------------+---------+------------------------------+---------+----------------------------------------------+
| 1 | SIMPLE | eu | ALL | NULL | NULL | NULL | NULL | 7832817 | Using where; Using temporary; Using filesort |
| 1 | SIMPLE | euf | ref | entityusage_id | entityusage_id | 108 | func | 1 | Using index condition |
| 1 | SIMPLE | t | eq_ref | PRIMARY,album | PRIMARY | 108 | trackerdatabase.euf.track_id | 1 | Using where |
+------+-------------+-------+--------+----------------+----------------+---------+------------------------------+---------+----------------------------------------------+
爲什麼'eu.updated'並不直接,但'date_format'組合後? – i486
運行在歐盟每一行更新的日期格式會降低速度。可能想看看你如何存儲數據並在插入時做這些工作。 –
可能是一個錯字。但是'date_format(eu.updated,'%Y-%m-%d')!= date_format(eu.updated,'%Y%m%d')' –