导致MySQL做全表扫描的几种情况
这两天看到了两种可能会导致全表扫描的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
我们可以看到,这个表有三个字段,其中两个int类型,一个varchar类型。varchar类型的字段score是一个索引,而id是主键。
然后我们给这个表里面插入一些数据,插入数据之后的表如下
mysqlyeyztest 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)
这个时候,我们使用explain语句来查看两条sql的执行情况,分别是
explain select from test where score ='10'; explain select from test where score =10;
结果如下
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)
可以看到,如果我们使用的是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)
当我们使用反向查找的时候,不会使用到索引,来看狼蚁网站SEO优化两条sql
explain select from test1 where score='111'; explain select from test1 where score!='111';
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)
可以看到,使用!=作为条件的时候,扫描的行数是表的总记录行数。如果想要使用索引,我们就不能使用反向匹配规则。
情况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 | c | | 4 | yeyz | | NULL | yeyz | +------+------+ 5 rows in set (0.00 sec)
其中表test4包含两个字段,id字段是一个索引,而name字段是varchar类型,我们来看狼蚁网站SEO优化三个语句的扫描行数
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: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)
可以看到单独使用id=1和id is null,都只会扫描一行记录,而使用or将二者连接起来就会导致扫描全表而不使用索引。
简单一下
1.强制类型转换的情况下,不会使用索引,会走全表扫描
2.反向查询不能使用索引,会导致全表扫描。
3.某些or值条件可能导致全表扫描。
以上就是导致MySQL做全表扫描的几种情况的详细内容,更多关于MySQL 全表扫描的资料请关注狼蚁SEO其它相关文章!
编程语言
- 如何快速学会编程 如何快速学会ug编程
- 免费学编程的app 推荐12个免费学编程的好网站
- 电脑怎么编程:电脑怎么编程网咯游戏菜单图标
- 如何写代码新手教学 如何写代码新手教学手机
- 基础编程入门教程视频 基础编程入门教程视频华
- 编程演示:编程演示浦丰投针过程
- 乐高编程加盟 乐高积木编程加盟
- 跟我学plc编程 plc编程自学入门视频教程
- ug编程成航林总 ug编程实战视频
- 孩子学编程的好处和坏处
- 初学者学编程该从哪里开始 新手学编程从哪里入
- 慢走丝编程 慢走丝编程难学吗
- 国内十强少儿编程机构 中国少儿编程机构十强有
- 成人计算机速成培训班 成人计算机速成培训班办
- 孩子学编程网上课程哪家好 儿童学编程比较好的
- 代码编程教学入门软件 代码编程教程