[英]mysql group by joined column too slow
我有兩個表events
和event_params
第一個表使用這些列存儲事件
events | CREATE TABLE `events` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`project` varchar(24) NOT NULL,
`event` varchar(24) NOT NULL,
`date` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `project` (`project`,`event`)
) ENGINE=InnoDB AUTO_INCREMENT=2915335 DEFAULT CHARSET=latin1
第二個使用這些列存儲每個事件的參數
event_params | CREATE TABLE `event_params` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`event_id` int(10) unsigned NOT NULL,
`name` varchar(24) NOT NULL,
`value` varchar(524) CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`id`),
KEY `name` (`name`),
KEY `event_id` (`event_id`),
KEY `value` (`value`),
) ENGINE=InnoDB AUTO_INCREMENT=20789391 DEFAULT CHARSET=latin1
現在我想獲取在指定參數上具有各種值的事件計數
我為campaign
參數編寫了此查詢,但這太慢了(響應時間為15秒)
SELECT
event_params.value as campaign,
count(*) as count
FROM `events`
left join event_params on event_params.event_id = events.id
and event_params.name = 'campaign'
WHERE events.project = 'foo'
GROUP by event_params.value
這是EXPLAIN
查詢結果:
+----+-------------+--------------+------------+------+---------------------+----------+---------+------------------+------+----------+----------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------------+------------+------+---------------------+----------+---------+------------------+------+----------+----------------------------------------------+
| 1 | SIMPLE | events | NULL | ref | project | project | 26 | const | 1 | 100.00 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | event_params | NULL | ref | name,event_id,value | event_id | 4 | events.events.id | 4 | 100.00 | Using where |
+----+-------------+--------------+------------+------+---------------------+----------+---------+------------------+------+----------+----------------------------------------------+
我可以加快查詢速度嗎?
您可以嘗試在event_params
表上添加以下索引,這可以加快連接速度:
CREATE INDEX idx1 ON event_params (event_id, name, value);
由於COUNT
操作涉及對每個記錄進行計數,因此可能無法對聚合步驟進行太多優化。
將“廣告系列值”移動到主表中,並為VARCHAR
輸入合適的長度,然后
SELECT
campaign,
count(*) as count
FROM `events`
WHERE project = 'foo'
GROUP by campaign
並有
INDEX(project, campaign)
嘗試使用EAV時的一些建議:將“重要”值移到主表中; 在另一個表中只保留很少使用或很少設置的“值”。 另外(假設沒有公仔),有
PRIMARY KEY(event_id, name)
更多討論: http : //mysql.rjweb.org/doc.php/eav
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.