mysql - 为什么 LEFT JOIN 比 INNER JOIN 慢?

标签 mysql join query-optimization

我有两个查询,第一个(内连接)超快,第二个(左连接)超慢。如何使第二个查询更快?

EXPLAIN SELECT saved.email FROM saved INNER JOIN finished ON finished.email = saved.email;

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  finished    index   NULL    email   258 NULL    32168   Using index
1   SIMPLE  saved   ref email   email   383 func    1   Using where; Using index

EXPLAIN SELECT saved.email FROM saved LEFT JOIN finished ON finished.email = saved.email;

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   SIMPLE  saved   index   NULL    email   383 NULL    40971   Using index
1   SIMPLE  finishedindex   NULL    email   258 NULL    32168   Using index

编辑:我在下面为两个表格添加了表格信息。

CREATE TABLE `saved` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `slug` varchar(255) DEFAULT NULL,
  `email` varchar(127) NOT NULL,
  [omitted fields include varchar, text, longtext, int],
  PRIMARY KEY (`id`),
  KEY `slug` (`slug`),
  KEY `email` (`email`)
) ENGINE=MyISAM AUTO_INCREMENT=56329 DEFAULT CHARSET=utf8;

CREATE TABLE `finished` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `slug` varchar(255) DEFAULT NULL,
  `submitted` int(11) DEFAULT NULL,
  `status` int(1) DEFAULT '0',
  `name` varchar(255) DEFAULT NULL,
  `email` varchar(255) DEFAULT NULL,
  [omitted fields include varchar, text, longtext, int],
  PRIMARY KEY (`id`),
  KEY `assigned_user_id` (`assigned_user_id`),
  KEY `event_id` (`event_id`),
  KEY `slug` (`slug`),
  KEY `email` (`email`),
  KEY `city_id` (`city_id`),
  KEY `status` (`status`),
  KEY `recommend` (`recommend`),
  KEY `pending_user_id` (`pending_user_id`),
  KEY `submitted` (`submitted`)
) ENGINE=MyISAM AUTO_INCREMENT=33063 DEFAULT CHARSET=latin1;

最佳答案

对于INNER JOIN,MySQL一般会从行数最少的表开始。在这种情况下,它从表 finished 开始,并使用 saved.email 上的索引在 saved 中查找相应的记录。

对于 LEFT JOIN,(不包括一些优化)MySQL 通常按顺序连接记录(从最左边的表开始)。在这种情况下,MySQL 从表 saved 开始,然后尝试在 finished 中找到每个对应的记录。由于 finished.email 上没有可用索引,因此它必须对每次查找进行全面扫描。

编辑

现在您发布了您的模式,我可以看到 MySQL 在从 utf8latin1 时忽略了索引 (finished.email) > 字符集。您还没有发布每一列的字符集和排序规则,所以我将使用表的默认字符集。排序规则必须兼容,MySQL 才能使用索引。

MySQL 可以强制(升级)一个 latin1 排序规则,这是非常有限的,直到一个 utf8 排序规则,例如 unicode_ci(所以第一个查询可以通过将 latin1 排序规则升级为 utf8 来使用 saved.email 上的索引,但反之则不然(第二个查询可以不要在 finished.email 上使用索引,因为它无法将 utf8 排序规则降级为 latin1)。

解决方案是将两个电子邮件列更改为兼容的排序规则,也许最简单的方法是使它们具有相同的字符集和排序规则。

关于mysql - 为什么 LEFT JOIN 比 INNER JOIN 慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27787269/

相关文章:

php - 尝试通过从所选表中获取列名来构建查询

mysql - 如何在MySQL中将表与条件的结果字段连接起来

php - 如何使用提交按钮根据 id 更新数据库元素

caching - Spark SQL : how to cache sql query result without using rdd. 缓存()

sql - Mysql查询优化

mysql - 优化mysql查询

javascript - 如何创建一个根据数据库条目不断更新的进度条

sql - 如何有效地在 SQL 中进行连接的交集?

mysql - 两者上的 SQL JOIN

sql-server - 显示来自 Join 查询的不同数据