≡
  • 网络编程
  • 数据库
  • CMS技巧
  • 软件编程
  • PHP笔记
  • JavaScript
  • MySQL
位置:首页 > 数据库 > MySQL

解决导致MySQL做全表扫描的问题

人气:249 时间:2021-07-08

这篇文章主要为大家详细介绍了解决导致MySQL做全表扫描的问题,具有一定的参考价值,可以用来参考一下。

感兴趣的小伙伴,下面一起跟随四海网的小玲来看看吧!

目录
  • 情况1:
  • 情况2:
  • 情况3:
  • 简单总结一下:

     这两天看到了两种可能会导致全表扫描的sql,这里给大家看一下,希望可以避免踩坑:

 

情况1:

强制类型转换的情况下,不会使用索引,会走全表扫描。

举例如下:

首先我们创建一个表

代码如下:


 CREATE TABLE `test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `age` int(11) DEFAULT NULL,
  `score` varchar(20) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`),
  KEY `idx_score` (`score`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8

导致MySQL做全表扫描的几种情况

我们可以看到,这个表有三个字段,其中两个int类型,一个varchar类型。varchar类型的字段score是一个索引,而id是主键。

然后我们给这个表里面插入一些数据,插入数据之后的表如下:

代码如下:


mysql:yeyztest 21:43:12>>select * from test;
+----+------+-------+
| id | age  | score |
+----+------+-------+
|  1 |    1 | 5     |
|  2 |    2 | 10    |
|  5 |    5 | 25    |
|  8 |    8 | 40    |
|  9 |    2 | 45    |
| 10 |    5 | 50    |
| 11 |    8 | 55    |
+----+------+-------+
7 rows in set (0.00 sec)

导致MySQL做全表扫描的几种情况

这个时候,我们使用explain语句来查看两条sql的执行情况,分别是:

代码如下:


explain select * from test where score ='10';

explain select * from test where score =10;

导致MySQL做全表扫描的几种情况

结果如下:

代码如下:


mysql:yeyztest 21:42:29>>explain select * from test where score ='10';
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key       | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | test  | NULL       | ref  | idx_score     | idx_score | 62      | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+-----------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

mysql:yeyztest 21:43:06>>explain select * from test where score =10;  
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | test  | NULL       | ALL  | idx_score     | NULL | NULL    | NULL |    7 |    14.29 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 3 warnings (0.00 sec)

导致MySQL做全表扫描的几种情况

    可以看到,如果我们使用的是varchar类型的值,那么结果中扫描的行数rows就是1,而当我们使用的是整数值10的时候,扫描行数变为了7,证明,如果出现了强制类型转换,则会导致索引失效。

 

情况2:

   反向查询不能使用索引,会导致全表扫描。

创建一个表test1,它的主键是score,然后插入6条数据:

代码如下:


CREATE TABLE `test1` (
  `score` varchar(20) not null default '' ,
  PRIMARY KEY (`score`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

mysql:yeyztest 22:09:37>>select * from test1;
+-------+
| score |
+-------+
| 111   |
| 222   |
| 333   |
| 444   |
| 555   |
| 666   |
+-------+
6 rows in set (0.00 sec)

导致MySQL做全表扫描的几种情况

    当我们使用反向查找的时候,不会使用到索引,来看下面两条sql:

代码如下:


explain select * from test1 where score='111';

explain select * from test1 where score!='111';

导致MySQL做全表扫描的几种情况

代码如下:


mysql:yeyztest 22:13:01>>explain select * from test1 where score='111';
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | test1 | NULL       | const | PRIMARY       | PRIMARY | 62      | const |    1 |   100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

mysql:yeyztest 22:13:08>>explain select * from test1 where score!='111';
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
| id | select_type | table | partitions | type  | possible_keys | key     | key_len | ref  | rows | filtered | Extra                    |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
|  1 | SIMPLE      | test1 | NULL       | index | PRIMARY       | PRIMARY | 62      | NULL |    6 |   100.00 | Using where; Using index |
+----+-------------+-------+------------+-------+---------------+---------+---------+------+------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)

导致MySQL做全表扫描的几种情况

   可以看到,使用!=作为条件的时候,扫描的行数是表的总记录行数。因此如果想要使用索引,我们就不能使用反向匹配规则。

 

情况3:

  某些or值条件可能导致全表扫描。

首先我们创建一个表,并插入几条数据:

代码如下:


CREATE TABLE `test4` (
  `id` int(11) DEFAULT NULL,
  `name` varchar(20) DEFAULT NULL,
  KEY `idx_id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql--dba_admin@127.0.0.1:yeyztest 22:23:44>>select * from test4;
+------+------+
| id   | name |
+------+------+
|    1 | aaa  |
|    2 | bbb  |
|    3 | ccc  |
|    4 | yeyz |
| NULL | yeyz |
+------+------+
5 rows in set (0.00 sec)

导致MySQL做全表扫描的几种情况

   其中表test4包含两个字段,id字段是一个索引,而name字段是varchar类型,我们来看下面三个语句的扫描行数:

代码如下:


explain select * from test4 where id=1;

explain select * from test4 where id is null;

explain select * from test4 where id=1 or id is null;

导致MySQL做全表扫描的几种情况

代码如下:


mysql:yeyztest 22:24:12>>explain select * from test4 where id is null;
+----+-------------+-------+------------+------+---------------+--------+---------+-------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key    | key_len | ref   | rows | filtered | Extra                 |
+----+-------------+-------+------------+------+---------------+--------+---------+-------+------+----------+-----------------------+
|  1 | SIMPLE      | test4 | NULL       | ref  | idx_id        | idx_id | 5       | const |    1 |   100.00 | Using index condition |
+----+-------------+-------+------------+------+---------------+--------+---------+-------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)

mysql:yeyztest 22:24:17>>explain select * from test4 where id=1;                      
+----+-------------+-------+------------+------+---------------+--------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key    | key_len | ref   | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+--------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | test4 | NULL       | ref  | idx_id        | idx_id | 5       | const |    1 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+--------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

mysql:yeyztest 22:24:28>>explain select * from test4 where id=1 or id is null;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | test4 | NULL       | ALL  | idx_id        | NULL | NULL    | NULL |    5 |    40.00 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

导致MySQL做全表扫描的几种情况

   可以看到单独使用id=1和id is null,都只会扫描一行记录,而使用or将二者连接起来就会导致扫描全表而不使用索引。

 

简单总结一下:

1.强制类型转换的情况下,不会使用索引,会走全表扫描

2.反向查询不能使用索引,会导致全表扫描。

3.某些or值条件可能导致全表扫描。

以上就是导致MySQL做全表扫描的几种情况的详细内容,更多关于MySQL 全表扫描的资料请关注四海网其它相关文章!

本文来自:http://www.q1010.com/177/19300-0.html

注:关于解决导致MySQL做全表扫描的问题的内容就先介绍到这里,更多相关文章的可以留意四海网的其他信息。

关键词:

您可能感兴趣的文章

上一篇:MySQL MySQLadmin客户端用法示例
下一篇:解决MySQL too many connections错误的问题
热门文章
  • mysql 修改character_set_server为utf-8的简单示例
  • 解决MySQL丢失文件localhost.localdomain.pid、mysql.sock的示例
  • MySQL 数据类型binary和varbinary的简单示例
  • MySQL:reading initial communication packet问题解决方法
  • MySql 表类型MYISAM、InnoDB区别
  • bash: mysql: command not found 的解决方法
  • MYSQL默认用户名ROOT修改方法
  • MySQL 常用命令菜鸟教程
  • MySQL 使用命令行新建用户并授予权限
  • MySql 数据库物理文件存放位置查看示例
  • 最新文章
    • MySQL查看死锁与解除死锁的简单示例
    • MySQL 慢查询的功能实例
    • MySQL查看死锁与去除死锁的简单示例
    • MySQL找出未提交事务的SQL的简单示例
    • MySQL锁阻塞的的简单示例
    • MySQL中的binary类型使用操作的示例
    • SQL优化教程之in与range查询的简单示例
    • MySQL 的 21 个规范、优化最佳实践!
    • MySQL 字符类型大小写敏感的简单示例
    • 解决mybatis-plus分页传入参数后sql where条件没有limit分页信息的问题

四海网收集整理一些常用的php代码,JS代码,数据库mysql等技术文章。