简体   繁体   English

mysql group by join列太慢

[英]mysql group by joined column too slow

I have two tables events and event_params 我有两个表eventsevent_params

the first table stores the events with these columns 第一个表使用这些列存储事件

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

and second stores parameters for each event with these columns 第二个使用这些列存储每个事件的参数

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

now I want to get count of events those have various values on a specified parameter 现在我想获取在指定参数上具有各种值的事件计数

I wrote this query for campaign parameter but this is too slow (15 secs to respond) 我为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

and here is the EXPLAIN query result: 这是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                                  |
+----+-------------+--------------+------------+------+---------------------+----------+---------+------------------+------+----------+----------------------------------------------+

can i speed up this query ? 我可以加快查询速度吗?

You may try adding the following index on the event_params table, which might speed up the join: 您可以尝试在event_params表上添加以下索引,这可以加快连接速度:

CREATE INDEX idx1 ON event_params (event_id, name, value);

The aggregation step probably can't be optimized much because the COUNT operation involves counting each record. 由于COUNT操作涉及对每个记录进行计数,因此可能无法对聚合步骤进行太多优化。

Move the "campaign value" into the main table, with a suitable length for VARCHAR and then 将“广告系列值”移动到主表中,并为VARCHAR输入合适的长度,然后

SELECT
    campaign,
    count(*) as count
FROM `events`
WHERE project = 'foo'
GROUP by campaign

And have 并有

INDEX(project, campaign)

A bit of advice when tempted to use EAV: Move the 'important' values into the main table; 尝试使用EAV时的一些建议:将“重要”值移到主表中; leave only the rarely used or rarely set 'values' in the other table. 在另一个表中只保留很少使用或很少设置的“值”。 Also (assuming there are no dups), have 另外(假设没有公仔),有

PRIMARY KEY(event_id, name)

More discussion: http://mysql.rjweb.org/doc.php/eav 更多讨论: http : //mysql.rjweb.org/doc.php/eav

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM