導(dǎo)致MySQL做全表掃描的幾種情況
這兩天看到了兩種可能會(huì)導(dǎo)致全表掃描的sql,這里給大家看一下,希望可以避免踩坑:
情況1:
強(qiáng)制類型轉(zhuǎn)換的情況下,不會(huì)使用索引,會(huì)走全表掃描。
舉例如下:
首先我們創(chuàng)建一個(gè)表
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
我們可以看到,這個(gè)表有三個(gè)字段,其中兩個(gè)int類型,一個(gè)varchar類型。varchar類型的字段score是一個(gè)索引,而id是主鍵。
然后我們給這個(gè)表里面插入一些數(shù)據(jù),插入數(shù)據(jù)之后的表如下:
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)
這個(gè)時(shí)候,我們使用explain語句來查看兩條sql的執(zhí)行情況,分別是:
explain select * from test where score ='10'; explain select * from test where score =10;
結(jié)果如下:
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類型的值,那么結(jié)果中掃描的行數(shù)rows就是1,而當(dāng)我們使用的是整數(shù)值10的時(shí)候,掃描行數(shù)變?yōu)榱?,證明,如果出現(xiàn)了強(qiáng)制類型轉(zhuǎn)換,則會(huì)導(dǎo)致索引失效。
情況2:
反向查詢不能使用索引,會(huì)導(dǎo)致全表掃描。
創(chuàng)建一個(gè)表test1,它的主鍵是score,然后插入6條數(shù)據(jù):
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)
當(dāng)我們使用反向查找的時(shí)候,不會(huì)使用到索引,來看下面兩條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)
可以看到,使用!=作為條件的時(shí)候,掃描的行數(shù)是表的總記錄行數(shù)。因此如果想要使用索引,我們就不能使用反向匹配規(guī)則。
情況3:
某些or值條件可能導(dǎo)致全表掃描。
首先我們創(chuàng)建一個(gè)表,并插入幾條數(shù)據(jù):
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)
其中表test4包含兩個(gè)字段,id字段是一個(gè)索引,而name字段是varchar類型,我們來看下面三個(gè)語句的掃描行數(shù):
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)
可以看到單獨(dú)使用id=1和id is null,都只會(huì)掃描一行記錄,而使用or將二者連接起來就會(huì)導(dǎo)致掃描全表而不使用索引。
簡單總結(jié)一下:
1.強(qiáng)制類型轉(zhuǎn)換的情況下,不會(huì)使用索引,會(huì)走全表掃描
2.反向查詢不能使用索引,會(huì)導(dǎo)致全表掃描。
3.某些or值條件可能導(dǎo)致全表掃描。
以上就是導(dǎo)致MySQL做全表掃描的幾種情況的詳細(xì)內(nèi)容,更多關(guān)于MySQL 全表掃描的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
MySQL 有關(guān)MHA搭建與切換的幾個(gè)錯(cuò)誤log匯總
這篇文章主要介紹了MySQL 有關(guān)MHA搭建與切換的幾個(gè)錯(cuò)誤log匯總,幫助大家更好的理解和使用MySQL,感興趣的朋友可以了解下2020-12-12
MySQL使用TEXT/BLOB類型的知識(shí)點(diǎn)詳解
在本篇文章里小編給大家整理的是關(guān)于MySQL使用TEXT/BLOB類型的幾點(diǎn)注意內(nèi)容,有興趣的朋友們學(xué)習(xí)下。2020-03-03
Mysql中int(1)、int(20)的區(qū)別小結(jié)
本文主要介紹了Mysql中int(1)、int(20)的區(qū)別小結(jié),int后的數(shù)字表示最大顯示寬度,一般int后面的數(shù)字M要配合zerofill一起使用才有效,下面就來具體介紹一下,感興趣的可以了解一下2025-03-03
Navicat Premiun遠(yuǎn)程連接MySQL報(bào)錯(cuò)10038解決方案
這篇文章主要介紹了Navicat Premiun遠(yuǎn)程連接MySQL報(bào)錯(cuò)10038解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11
從一個(gè)MySQL的例子來學(xué)習(xí)查詢語句
從一個(gè)MySQL的例子來學(xué)習(xí)查詢語句...2006-12-12

