【问题标题】:Table converted from myISAM to INNODB is slowing down a query从 myISAM 转换为 INNODB 的表正在减慢查询速度
【发布时间】:2021-03-20 06:20:40
【问题描述】:

我有一个从 myISAM 转换为 INNODB 的表,这会减慢查询速度。这是一个有很多索引的大表。 MyIsam(在 mysql5.6 上)立即返回结果,INNODB(在 mysql5.7 上)需要 2 到 3 秒。 fnota 是浮动的。 serieid 和 epnumber 是整数。知道为什么在执行 index_merge 时这需要更多时间吗?

在MYISAM TABLE上解释:


explain SELECT count( fnota ) , avg( fnota ) FROM myrates
          WHERE serieid =4376 AND epnumber ='149'\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: myrates
         type: ref
possible_keys: serieid,epnumber,serieid_2
          key: serieid_2
      key_len: 8
          ref: const,const
         rows: 8207
        Extra: Using index condition

解释 INNODB 表:

explain SELECT count( fnota ) , avg( fnota ) FROM myrates
          WHERE serieid =4376 AND epnumber ='149'\G
*************************** 1. row ***************************
          id: 1
 select_type: SIMPLE
       table: myrates
  partitions: NULL
        type: index_merge
possible_keys: serieid,epnumber,serieid_2
         key: serieid,epnumber,serieid_2
     key_len: 4,4,8
         ref: NULL
        rows: 2
    filtered: 100.00
       Extra: Using intersect(serieid,epnumber,serieid_2); Using where

索引:


SHOW INDEX FROM myrates;
+---------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table   | Non_unique | Key_name  | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| myrates |          0 | fbid      |            1 | userid      | A         |     1405506 |     NULL | NULL   |      | BTREE      |         |               |
| myrates |          0 | fbid      |            2 | serieid     | A         |     8617224 |     NULL | NULL   |      | BTREE      |         |               |
| myrates |          0 | fbid      |            3 | epnumber    | A         |   139638192 |     NULL | NULL   |      | BTREE      |         |               |
| myrates |          1 | serieid   |            1 | serieid     | A         |      257656 |     NULL | NULL   |      | BTREE      |         |               |
| myrates |          1 | epnumber  |            1 | epnumber    | A         |       93431 |     NULL | NULL   |      | BTREE      |         |               |
| myrates |          1 | serieid_2 |            1 | serieid     | A         |      186213 |     NULL | NULL   |      | BTREE      |         |               |
| myrates |          1 | serieid_2 |            2 | epnumber    | A         |     3309332 |     NULL | NULL   |      | BTREE      |         |               |
| myrates |          1 | userid    |            1 | userid      | A         |      866339 |     NULL | NULL   |      | BTREE      |         |               |
| myrates |          1 | userid    |            2 | serieid     | A         |     4656575 |     NULL | NULL   |      | BTREE      |         |               |
+---------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
SHOW CREATE TABLE MYRATES; 
Table: myrates
Create Table: CREATE TABLE `myrates` (
  `userid` bigint(10) NOT NULL,
  `serieid` int(6) NOT NULL,
  `epnumber` float NOT NULL,
  `nota` int(6) NOT NULL DEFAULT '0',
  `fnota` float NOT NULL,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY `fbid` (`userid`,`serieid`,`epnumber`),
  KEY `serieid` (`serieid`),
  KEY `epnumber` (`epnumber`),
  KEY `serieid_2` (`serieid`,`epnumber`),
  KEY `userid` (`userid`,`serieid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

【问题讨论】:

  • 我会运行ANALYZE TABLE myrates 以确保索引统计信息是最新的。我同意这很奇怪,如果它还使用复合索引,则没有理由使用索引合并。我以前从未见过这样的解释。

标签: mysql optimization innodb myisam


【解决方案1】:

DESCRIBE 没有准确地拼出您拥有的索引。请提供SHOW CREATE TABLE。听起来您对一长串重叠索引感到困惑。

如果您有一个复合索引,例如(serieid, epnumber),您就不需要(serieid)。删除后一个索引以“解决”问题。

鉴于“fbid”的两列都以相同的顺序开头,因此键“userid”似乎也是多余的。

【讨论】:

  • 我编辑了帖子并添加了。我有这 2 个“冗余”索引 serieid 和 epnumber 的原因是因为我有一些查询,我只查找 epnumber。或仅适用于 serieid 。你觉得只有 serieid_2 就够了吗?
  • @AlexPalombo - 当你有INDEX(a,b),你就不需要INDEX(a)。前者将处理后者处理的任何查询。事实上,我见过一种情况,后者妨碍了前者的使用。也就是说,优化器选择了较短的索引,即使 2 列索引更适合查询。
猜你喜欢
  • 1970-01-01
  • 2010-11-16
  • 1970-01-01
  • 2021-09-28
  • 2016-06-14
  • 2011-10-04
  • 1970-01-01
  • 2017-12-24
  • 1970-01-01
相关资源
最近更新 更多