成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

聊聊索引失效的經典場景

數據庫 MySQL
因為在有多個索引的情況下,MySQL優化器一般會通過比較掃描行數、是否需要臨時表以及是否需要排序等,來作為選擇索引的判斷依據。

前置條件

數據庫版本為5.7.17。

創建一張user表,預置500w條數據,每個字段的值都是前綴加上從0開始計數的數字,累加到5000000,如圖:

然后用explain來解析一下有沒有走索引。

最左匹配原則

我們首先建一個組合索引,username,jobno,company三個字段:

首先執行以下幾個sql:

EXPLAIN SELECT * FROM `user` WHERE username = 'cxj1000000' AND jobno = 'jn1000000' AND company = 'com1000000';
EXPLAIN SELECT * FROM `user` WHERE username = 'cxj1000000';
EXPLAIN SELECT * FROM `user` WHERE username = 'cxj1000000' AND jobno = 'jn1000000';
EXPLAIN SELECT * FROM `user` WHERE jobno = 'jn1000000' AND username = 'cxj1000000';
EXPLAIN SELECT * FROM `user` WHERE username = 'cxj1000000' AND company = 'com1000000';

發現都走了索引。

接下來再執行幾個sql:

EXPLAIN SELECT * FROM `user` WHERE jobno = 'jn1000000' AND company = 'com1000000';
EXPLAIN SELECT * FROM `user` WHERE company = 'com1000000';
EXPLAIN SELECT * FROM `user` WHERE jobno = 'jn1000000' ;

發現沒有走索引。

結論:最左匹配原則要求查詢的sql語句中,必須包含最左邊的字段,在username,jobno,company的組合索引中,username是最左邊的字段,那么查詢的sql語句中的where條件中,必須包含username字段,而與sql語句中username的使用順序無關。

索引列上有計算

根據主鍵ID查詢,毫無疑問會走主鍵索引,但如果像下面這種:

EXPLAIN SELECT * FROM `user` WHERE id + 1 = 2

可以看到沒有走索引。

總結:如果索引列參與了計算,不會命中索引。像這種情況可以變換一下等式,把運算放到等號右邊,就會命中索引。

EXPLAIN SELECT * FROM `user` WHERE id = 2 - 1

查詢條件帶or

上面所說的最左匹配原則中,只要查詢語句中包含username就會走索引,但如果我們把and條件換成or,即:

SELECT * FROM `user` WHERE username = 'cxj13' OR jobno = 'jn13'

可以看到并沒有走索引,而是全表掃描,所以在帶有or的查詢語句中,索引將失效,除非所有條件都帶有索引。也就是說,username有索引,jobno也必須要建一個索引才會生效。

like查詢

在username字段上新建索引user_idx_normal_username,不使用%模糊查詢:

SELECT * FROM `user` WHERE username LIKE 'cxj'

使用前置%:

使用后置%:

前后都用%:

結論:模糊查詢中,只要使用了%都不會走索引,不使用%號時可以走索引。

字段類型不同

還是使用username進行查詢,username的字段類型是字符串類型,我們知道以下語句:

SELECT * FROM `user` WHERE username = 'cxj13'

肯定是會走索引的,但如果我們不用引號引用起來,而是:

SELECT * FROM `user` WHERE username = 100

會發現沒有走索引:

結論:字符串的索引字段在查詢時數據需要用引號引用,否則索引失效。

查詢語句包含in

這種就比較特殊了,走不走索引不是絕對的,跟所查詢的數據量跟總表數據量的比例有關。

我們新建一張表:

CREATE TABLE `test` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`dept` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8

然后往這張表里插入10條數據:

首先執行以下語句:

SELECT * FROM test WHERE id IN (1)

執行結果:

可以看到走了索引,需要注意的是type,我們知道type表示所走索引的一個效率值,它的結果的好壞依次為:

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL。

一般來說,至少要達到range級別,當type=index或者ALL時,表示效率低下,需要優化。我們看到只查詢一條記錄時,不但走了索引,而且type=const,效率較高。我們擴大下范圍:

SELECT * FROM test WHERE id IN (1,2,3)

從執行結果上看,也走了索引,但此時type=range,效率降低了。再擴大下范圍:

SELECT * FROM test WHERE id IN (1,2,3,4,5)

可以看到沒有走索引了,type=ALL,全表掃描。

結論:mysql優化器會根據所查詢的數據量決定是走索引還是全表掃描。

mysql選錯索引

我們再建一個demo表來說明這種情況:

CREATE TABLE `demo` (
`id` int(11) NOT NULL,
`a` int(11) NOT NULL default 0,
`b` int(11) NOT NULL default 0,
PRIMARY KEY (`id`),
KEY `a` (`a`),
KEY `b` (`b`)
) ENGINE=InnoDB;

然后插入100w條數據,執行以下sql:

select * from demo where (a between 1000 and 2000) and (b between 50000 and 100000) limit 1

看一下執行情況:

可以看到走了索引a,且只掃描了1001行,其實這正是我們需要的。

但如果我們加個排序,變成這樣:

SELECT * FROM demo WHERE (a BETWEEN 1000 AND 2000) AND (b BETWEEN 50000 AND 100000) ORDER BY b LIMIT 1

再看下執行情況:

可以看到走了索引b,并且掃描了5w多行數據,這樣效率顯然會降低,為什么會走索引b呢?

因為在有多個索引的情況下,mysql優化器一般會通過比較掃描行數、是否需要臨時表以及是否需要排序等,來作為選擇索引的判斷依據。在這個例子中,優化器看到根據b來進行排序,認為使用b效率更高,所以走了索引b。實際上,我們應該使用a索引。

這種情況可以使用force index來強制使用索引a。

SELECT * FROM demo FORCE INDEX(a) WHERE (a BETWEEN 1000 AND 2000) AND (b BETWEEN 50000 AND 100000) ORDER BY b LIMIT 1;

可以看到,查詢走了索引a,并且只掃描了1001行。

責任編輯:姜華 來源: 今日頭條
相關推薦

2022-01-09 18:32:03

MySQL SQL 語句數據庫

2024-05-08 08:18:05

索引失效場景

2021-09-04 07:56:44

Spring事務失效

2024-04-19 13:57:30

索引數據庫查詢

2024-01-05 14:20:55

MySQL索引優化器

2020-12-09 10:10:24

MySQL數據庫算法

2022-02-28 08:55:31

數據庫MySQL索引

2024-05-07 08:23:03

Spring@Async配置

2022-02-14 16:53:57

Spring項目數據庫

2024-12-11 08:09:54

2025-05-28 00:00:01

MySQL場景索引

2019-07-21 09:17:11

數據緩存架構

2022-05-02 21:47:13

并發編程線程

2022-08-29 09:06:43

hippo4j動態線程池

2020-05-21 11:29:58

復刻手機屏幕

2023-09-28 09:07:54

注解失效場景

2020-12-08 09:45:07

MySQL數據庫索引

2024-10-15 08:37:08

2024-09-09 08:29:25

2024-01-29 08:28:01

Spring事務失效
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91精品国产91久久综合桃花 | 91亚洲精| www.伊人.com| 日韩一区精品 | 999精品视频 | 一区二区在线 | 婷婷激情在线 | 综合另类 | 最近日韩中文字幕 | 一级aaaa毛片 | 精品三级在线观看 | 久久精品一区二区三区四区 | 精品视频免费 | 毛片在线免费 | 精品91久久 | 盗摄精品av一区二区三区 | 夜夜草导航 | 国产精品久久精品 | 亚洲成人国产综合 | 日本爱爱视频 | 欧美中文字幕在线 | 国产原创视频 | 干一干操一操 | 亚洲欧美国产精品一区二区 | 一级黄片一级毛片 | 国产一区二区精品 | 一区二区三区国产 | 午夜视频免费在线观看 | 国产亚洲网站 | 日韩午夜一区二区三区 | 欧美精品一区二区三区在线播放 | 99精品视频免费观看 | 男女啪啪高潮无遮挡免费动态 | 黄色国产在线播放 | 韩日一区二区三区 | gav成人免费播放视频 | 玖玖在线精品 | 美女人人操 | 欧美日韩国产综合在线 | 91亚洲精 | www.黄色网|