【问题标题】:MySQL query not using indexMySQL查询不使用索引
【发布时间】:2013-07-10 07:57:13
【问题描述】:

我有一个运行非常缓慢的 MySQL 查询,因为它没有使用连接键上的索引。我的表结构有什么问题,优化器没有使用索引?

mysql> EXPLAIN SELECT *  FROM indicator_performance_averages
LEFT OUTER JOIN `prof` ON (`prof`.`symbol` = indicator_performance_averages.`symbol`) 
WHERE (indicator_performance_averages.`symbol` = 'ZCN13');
+----+-------------+--------------------------------+-------+---------------+------------+---------+-------+---------+-------+
| id | select_type | table                          | type  | possible_keys | key        | key_len | ref   | rows    | Extra |
+----+-------------+--------------------------------+-------+---------------+------------+---------+-------+---------+-------+
|  1 | SIMPLE      | indicator_performance_averages | const | idx_symbol    | idx_symbol | 98      | const |       1 |       |
|  1 | SIMPLE      | prof                           | ALL   | NULL          | NULL       | NULL    | NULL  | 1102075 |       |
+----+-------------+--------------------------------+-------+---------------+------------+---------+-------+---------+-------+

mysql> DESCRIBE indicator_performance_averages;
+--------------------+------------------+------+-----+---------+----------------+
| Field              | Type             | Null | Key | Default | Extra          |
+--------------------+------------------+------+-----+---------+----------------+
| id                 | int(11) unsigned | NO   | PRI | NULL    | auto_increment |
| symbol             | varchar(32)      | NO   | UNI | NULL    |                |
| date               | date             | YES  |     | NULL    |                |
| last_update        | timestamp        | YES  |     | NULL    |                |
+--------------------+------------------+------+-----+---------+----------------+

mysql> DESCRIBE prof;
+---------------+---------------------+------+-----+---------------------+----------------+
| Field         | Type                | Null | Key | Default             | Extra          |
+---------------+---------------------+------+-----+---------------------+----------------+
| id            | bigint(20) unsigned | NO   | PRI | NULL                | auto_increment |
| symbol        | varchar(32)         | NO   | UNI | NULL                |                |
| name          | varchar(128)        | NO   |     | NULL                |                |
| lastupdate    | datetime            | NO   |     | 0000-00-00 00:00:00 |                |
+---------------+---------------------+------+-----+---------------------+----------------+

编辑:为两个表添加 SHOW CREATE TABLE:

CREATE TABLE `indicator_performance_averages` (
  `id` int(11) unsigned NOT NULL auto_increment,
  `symbol` varchar(32) character set utf8 NOT NULL,
  `date` date default NULL,
  `last_update` timestamp NULL default NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `idx_symbol` (`symbol`)
) ENGINE=InnoDB AUTO_INCREMENT=6719 DEFAULT CHARSET=latin1

CREATE TABLE `prof` (
  `id` bigint(20) unsigned NOT NULL auto_increment,
  `symbol` varchar(32) NOT NULL,
  `name` varchar(128) NOT NULL,
  `lastupdate` datetime NOT NULL default '0000-00-00 00:00:00',
  PRIMARY KEY  (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`),
  UNIQUE KEY `IDX_symbol` (`symbol`),
) ENGINE=InnoDB AUTO_INCREMENT=37736071 DEFAULT CHARSET=latin1

【问题讨论】:

  • MySQl 在 JOIN 上使用 indicator_performance_averages.idx_symbol 索引。它只会在 JOIN 上使用一个索引,因为它已经知道另一侧的值。
  • 使用什么字符集对各个 symbol 列进行编码?
  • 我们希望prof.symbol 上的唯一键出现在计划中的 possible_keys 列中。这里没有足够的信息来调试问题。我认为我们需要SHOW CREATE TABLE 的两个表的输出,以便识别问题。由于这是一个 VARCHAR 列,因此可能怀疑是字符集或排序规则的差异。
  • @mike-w,我不明白这有什么帮助。为什么不能使用索引来查找prof表中的值?
  • @eggyal 你让我兴奋了一分钟,因为一个是 utf8,另一个是 latin1,但是当我切换到 latin1 时,我仍然遇到同样的问题。

标签: mysql join indexing


【解决方案1】:

问题是indicator_performance_averages.symbol 上的character set utf8 与prof.symbol 上的character set latin1 不匹配。

这会阻止 MySQL 在 prof.symbol 上使用索引。

要获得可用于查询计划的索引,您需要转换谓词中的字符集以匹配列的数据类型。尝试将连接谓词更改为此...

ON (`prof`.`symbol` = CONVERT(indicator_performance_averages.`symbol` USING latin1)

(我认为这是正确的语法。我们试图让 MySQL 从 ipa 表中获取 utf8 值,并将其转换为 latin1,然后再查找 prof 表。CAST () 函数也可以使用。)

【讨论】:

  • 谢谢。我使用navicat调整了表格的字符集,但没有意识到这不会调整各个字段。
  • @Colin M:我犹豫是否建议您更改列的字符集,因为这样设置可能是有原因的。是的,表的字符集是添加新列时将使用的默认值。创建列时,字符集实际上是在每列级别指定的。但是更方便的是不必在每个字符列上都指定它,让列“继承”表的设置,表在创建时从数据库继承,数据库在创建时从实例继承。
猜你喜欢
  • 2020-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-29
  • 1970-01-01
相关资源
最近更新 更多