走索引+回表还是走主键扫描?

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sun_ashe/article/details/83991504

走索引+回表还是走主键扫描?

一个非索引覆盖类型的查询,走主键还是走索引回表?MySQL可能会在这个问题上选择错误。

比如说一张表t1,表结构如下

mysql> show create table t1\G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `id1` int(11) DEFAULT NULL,
  `id2` int(11) DEFAULT NULL,
  `id3` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `id1` (`id1`),
  KEY `id2` (`id2`)
) ENGINE=InnoDB AUTO_INCREMENT=1000001 DEFAULT CHARSET=utf8mb4

表中共有100000万条数据

mysql> select count(*) from t1;
+----------+
| count(*) |
+----------+
|  1000000 |
+----------+
1 row in set (3.77 sec)

针对于select * from t1 where id1=100;这条sql,MySQL有两种方式去获取正确的数据,第一是通过id1索引获取正确的主键值,拿主键值取获取对应的行数据;第二是直接通过主键索引进行扫描。

两种都可以,MySQL会粗略的计算CPU和磁盘消耗之后,选择一种,但经常性的会出错,如下:

mysql> explain select * from t1 where id1=100\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ALL
possible_keys: id1
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 1
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)

mysql> explain select * from t1 force index(id1)where id1=100\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ref
possible_keys: id1
          key: id1
      key_len: 5
          ref: const
         rows: 96
     filtered: 100.00
        Extra: NULL
1 row in set, 1 warning (0.00 sec)

而通常的解决办法无非有两种,

  • 对表进行optimize操作
  • force index强制索引选择。

如果选择force index,后期不能随意的删除这条索引,不然业务SQL就该操作了。

结论是无论什么情况下,我们不能绝对信任优化器会帮助我们选择正确的索引,选择恰当的时间进行干预,才能保证SQL的高效运行。

猜你喜欢

转载自blog.csdn.net/sun_ashe/article/details/83991504
今日推荐