为什么MySQL查询使用连接缓冲区?
下面的查询正在使用连接缓冲区,我想知道是否有人可以向我解释为什么会这样。只是想进一步了解mysql和索引为什么MySQL查询使用连接缓冲区?,mysql,join,indexing,Mysql,Join,Indexing,下面的查询正在使用连接缓冲区,我想知道是否有人可以向我解释为什么会这样。只是想进一步了解mysql和索引 mysql> EXPLAIN SELECT events.event_topic_id, event_topic_name, event_topic_image, event_type_name,city_name FROM events -> JOIN event_topic ON event_topic.event_topic_id=event
mysql> EXPLAIN SELECT events.event_topic_id, event_topic_name, event_topic_image, event_type_name,city_name FROM events
-> JOIN event_topic ON event_topic.event_topic_id=events.event_topic_id
-> JOIN event_type ON event_type.event_type_id = event_topic.event_type_id
-> JOIN locations ON locations.location_id=events.location_id
-> JOIN city ON city.city_id=locations.city_id
-> WHERE event_date > NOW()
-> GROUP BY events.event_topic_id, city.city_id;
+----+-------------+-------------+--------+---------------------------------------+-----------------+---------+--------------------------------------+------+----------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------------+--------+---------------------------------------+-----------------+---------+--------------------------------------+------+----------+----------------------------------------------+
| 1 | SIMPLE | city | index | PRIMARY | city_name | 52 | NULL | 6 | 100.00 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | locations | ref | PRIMARY,city_id | city_id | 1 | PremiumCONNECT.city.city_id | 1 | 100.00 | Using index |
| 1 | SIMPLE | events | ref | location_id,event_topic_id,event_date | location_id | 2 | PremiumCONNECT.locations.location_id | 3 | 100.00 | Using where |
| 1 | SIMPLE | event_type | index | PRIMARY | event_type_name | 52 | NULL | 2 | 100.00 | Using index; Using join buffer |
| 1 | SIMPLE | event_topic | eq_ref | PRIMARY,event_type_id | PRIMARY | 1 | PremiumCONNECT.events.event_topic_id | 1 | 100.00 | Using where |
+----+-------------+-------------+--------+---------------------------------------+-----------------+---------+--------------------------------------+------+----------+----------------------------------------------+
事件表:
CREATE TABLE `events` (
`event_id` smallint(8) unsigned NOT NULL AUTO_INCREMENT,
`location_id` smallint(3) unsigned NOT NULL,
`event_date` datetime NOT NULL,
`event_topic_id` tinyint(3) unsigned NOT NULL,
PRIMARY KEY (`event_id`),
KEY `location_id` (`location_id`),
KEY `event_topic_id` (`event_topic_id`),
KEY `event_date` (`event_date`),
CONSTRAINT `events_ibfk_2` FOREIGN KEY (`event_topic_id`) REFERENCES `event_topic` (`event_topic_id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `events_ibfk_3` FOREIGN KEY (`location_id`) REFERENCES `locations` (`location_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=91 DEFAULT CHARSET=latin1
事件主题表:
CREATE TABLE `event_topic` (
`event_topic_id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
`event_topic_name` varchar(100) DEFAULT NULL,
`event_topic_description` text NOT NULL,
`event_topic_cost` decimal(7,2) DEFAULT NULL,
`event_type_id` tinyint(3) unsigned NOT NULL,
`event_topic_clickthrough` tinytext,
`event_topic_length` varchar(6) NOT NULL,
`event_topic_image` varchar(41) DEFAULT NULL,
`event_topic_image_md5` char(32) NOT NULL,
PRIMARY KEY (`event_topic_id`),
KEY `event_type_id` (`event_type_id`),
KEY `topic_image_sha1` (`event_topic_image_md5`),
CONSTRAINT `event_topic_ibfk_1` FOREIGN KEY (`event_type_id`) REFERENCES `event_type` (`event_type_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=latin1
事件类型表:
CREATE TABLE `event_type` (
`event_type_id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
`event_type_name` varchar(50) NOT NULL,
`conf_email` text,
PRIMARY KEY (`event_type_id`),
KEY `event_type_name` (`event_type_name`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
位置表:
CREATE TABLE `locations` (
`location_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`location_name` varchar(50) NOT NULL,
`location_address` tinytext NOT NULL,
`location_capacity` smallint(6) NOT NULL,
`city_id` tinyint(3) unsigned NOT NULL,
`gps_coords` varchar(30) DEFAULT NULL,
PRIMARY KEY (`location_id`),
KEY `city_id` (`city_id`),
CONSTRAINT `locations_ibfk_1` FOREIGN KEY (`city_id`) REFERENCES `city` (`city_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=latin1
城市表:
CREATE TABLE `city` (
`city_id` tinyint(3) unsigned NOT NULL AUTO_INCREMENT,
`city_name` varchar(50) NOT NULL,
PRIMARY KEY (`city_id`),
UNIQUE KEY `city_name` (`city_name`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
正如在“”中所述:“来自早期联接的表以部分形式读入联接缓冲区,然后使用缓冲区中的行与当前表执行联接。”
因此,在您的例子中,您已经加入了event_主题,因此优化器能够使用来自加入缓冲区的event_主题内容
使用缓冲区是一件好事;您可能注意到EXPLAIN输出的第一行出现了不希望出现的“usingtemporary;usingfilesort”,这可能来自groupby,在本例中可能是不可避免的
顺便问一下,你会遇到城市名称“唯一”约束的问题吗?我想到了斯普林菲尔德(两个在新泽西州)、华盛顿、格林维尔等地。尝试使用:
"STRAIGHT_JOIN" and "FORCE INDEX":
EXPLAIN SELECT events.event_topic_id, event_topic_name, event_topic_image, event_type_name,city_name FROM events
-> straight_join event_topic force index(primary) ON event_topic.event_topic_id=events.event_topic_id
-> straight_join event_type force index(primary) ON event_type.event_type_id = event_topic.event_type_id
-> straight_join locations force index(primary) ON locations.location_id=events.location_id
-> straight_join city force index(primary) ON city.city_id=locations.city_id
-> WHERE event_date > NOW()
-> GROUP BY events.event_topic_id, city.city_id;
顺便说一句,使用连接缓冲区并不好。这意味着您需要改进或引用正确的索引。通常使用连接缓冲区是件好事(但也表明您的查询可能会被调整)。此执行计划看起来非常愚蠢。但是,对于表中给定的行数,引擎在所有表之间执行交叉连接的速度可能比找到一个好的执行计划要快。好的,这是有意义的。我之所以研究它,是因为mysqltuner抱怨有“在没有索引的情况下执行的联接”,我应该增加联接缓冲区大小或“总是使用带有联接的索引”。无论如何,您是否知道此查询需要缓冲多少信息?W.r.t由于城市是唯一的,此系统中的活动将仅在南非的主要城市举办,因此不会有任何同名的活动。谢谢你指出这一点!好吧,我认为你在为美国写一个系统是错误的。