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

一文帶你掌握in到底走不走索引?啥情況能走啥情況不能走

數據庫 其他數據庫
總體來說,in后面條件越少越好,假設一張表有1000萬條數據,in后面的條件有10000個,這時候就算走了range索引,估計效率也好不到哪里。

in到底用不用索引感覺像一樁懸疑片!古早時期的面經,統一說不走索引,在一些程序員腦海中從此留下不可磨滅的印記。有些從業時間較長的程序員腦子里的第一反應就是不走索引,上個月我就曾經被同事這樣質疑過。

但是那是mysql5.5以前的老黃歷了,現在都到8.0+了,5.5(甚至更早)以后可以肯定的是它會走索引。但必然走索引嗎?不一定。

我搜索引擎上搜索關鍵詞 in/or 和 索引,出來一大片文章,一般都會說,in/or能走索引,但后面跟的條件個數多了就不走索引了。但問題就來了,這個多了到底是多少才算多?對于一個動態查詢的SQL,我咋知道到底走不走索引?如何量化計算呢?

這時候就語焉不詳或者直接跳過。

大名鼎鼎的《阿里巴巴JAVA開發規范》倒是一刀切。最好不超過1000。

圖片圖片

人家這規范只是推薦,也不是強制,是吧,不能吐槽。

而且超過1000就算用上了range級別的查詢,那可能也快不到哪里去啊,對于要求快速響應的互聯網需求來說這推薦好像沒毛病。

但這不是重點,今天的重點在于,我一定要搞清楚,在保證explain 的type為range而不是ALL全表掃描的前提下,到底select * from table where id in (1,2,3.....x)這個x能到多少。

問題

首先建一張測試表,來一步復現一下,走與不走索引的情況。

mysql

版本:5.7.19 引擎:innodb

創建一個測試表

sql

 代碼解讀
復制代碼CREATE TABLE `t_person` (
  `id` int(11) NOT NULL,
  `name` varchar(10) COLLATE utf8_bin DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

使用SQL

EXPLAIN SELECT id, NAME FROM t_person WHERE id IN (1)

查看執行計劃

圖片圖片

此時表里無數據,顯示的是no matching row in const table.

少量數據

插入一條數據insert t_person (id,name) values(1,'張三')

使用SQL

EXPLAIN SELECT id, NAME FROM t_person WHERE id IN (1)

查看執行計劃

圖片圖片

使用了索引,還是效率最高的const(system生產環境不可能的吧),此時id in(1)相當于 id = 1。

在in里增加點條件。

sql變成EXPLAIN SELECT id, NAME FROM t_person WHERE id IN (1, 2)

查看執行計劃

圖片圖片

使用了索引,但級別下降到了range,即范圍索引。

繼續在in里增加條件。

sql變成EXPLAIN SELECT id, NAME FROM t_person WHERE id IN (1, 2,3)

查看執行計劃

圖片圖片

索引級別變成了ALL,即全表掃描,其實是索引失效了。

再往表里插入兩條數據。此時總共3條數據。

scss

 代碼解讀
復制代碼insert t_person (id,name) values(2,'李四')
insert t_person (id,name) values(3,'王五')

再使用sqlEXPLAIN SELECT id, NAME FROM t_person WHERE id IN (1, 2,3)

查看執行計劃

圖片圖片

可以看到,隨時表數據的增加,同樣的sql執行計劃從ALL變回了range,索引又生效了。

同樣地,再增加一個in條件,EXPLAIN SELECT id, NAME FROM t_person WHERE id IN (1,2,3,4)的執行計劃又變回了ALL,這里就不放圖了。

多點數據

以上只是小打小鬧撒撒水啦,總共幾條數據,in的條件都快超過表數據了,執行計算都不用預估就知道全表掃描還好一點啦。

我再往表里插入100萬條數據。

圖片圖片

我先按照阿里的開發規范推薦的1000這個值作為臨界值,先使用900個條件

圖片圖片

再使用1100個條件

圖片圖片

上圖表明,這兩種情況都使用到了range范圍索引呢。

再加大劑量,直接上10萬。

圖片圖片

步子邁大了,咔,這下終于全表掃描了。

但是還是沒找到臨界值。

官網上尋找答案

dev.mysql.com/doc/refman/…

我在這里尋找到了一個參數,描述的倒像是相似的問題。

圖片圖片

這個方法說的是當使用in或or查詢時,比如where in(1,2,3),執行引擎會先預估表中的數量,表中的數量將決定使用的查詢方式,比如,如果表中只有3條數據,那么很明顯,這時候直接全表掃描。

而這個預估的方法有2種,一是dive到index中即利用索引完成元組數的估算,簡稱index dive; 二是使用索引的統計數值,進行估算.

相比這2種方式,在效果上:

  • index dive: 速度慢,但能得到精確的值(MySQL的實現是數索引對應的索引項個數,所以精確)
  • index statistics: 速度快,但得到的值未必精確.

但eq_range_index_dive_limit這個參數確實跟今天的主題相關系數不大。很明顯,這個值在mysql 5.7是200, 一開始的in后面的條件個數就是900,依然是走了range索引的。

stackoverflow

于是我找到了stackoverflow,在上面把msyql in count 這些關鍵詞搜了一下,沒有找到相關的問題。

然后我把問題詳細描述了一下,提了一個新的問題,沒想到啊,半個小時不到,人家就直接給我點踩,并給出了相似的已解答問題。

尷尬了。我超喜歡stackoverflow,這里的人個個都是人才。

相似的問題在這里。

stackoverflow.com/questions/7…

這位仁兄也在in的使用中也有很多問號,in的條件卡在14000左右,超過就失去了range索引。

下面高贊答案提到了一個參數,range_optimizer_max_mem_size ,一看就很有搞頭啊。

圖片圖片

轉到mysql官網,憑我的渣渣英語也能看明白,我知道,大概我找到答案了。

dev.mysql.com/doc/refman/…

企業微信截圖企業微信截圖

要控制范圍優化器可用的內存,使用range_optimizer_max_mem_size系統變量:

  • 值為0表示“沒有限制”。
  • 當值大于0時,優化器將跟蹤在考慮范圍訪問方法時所消耗的內存。如果即將超過指定的限制,則放棄范圍訪問方法,轉而考慮其他方法,包括全表掃描。這可能不太理想。如果發生這種情況,會出現以下警告(其中N是當前的range_optimizer_max_mem_size值)。

現在事情就很簡單了。

圖片圖片

range_optimizer_max_mem_size默認是8M,使用同樣的SQL,in后面同樣的條件為固定的19900個,在range_optimizer_max_mem_size=8M,range_optimizer_max_mem_size=8情況下分別執行一下看效果。

range_optimizer_max_mem_size=8M時,走range索引。

圖片圖片

range_optimizer_max_mem_size=8時,走ALL全表掃描。

圖片圖片

破案了!

明明官網上就有答案,我卻三過家門而不入。

結論

in兩種情況會走全表掃描。

  • in后面條件導致sql(消耗內存)大小超過range_optimizer_max_mem_size。 
  • in后面條件個數接近或者等于表數量,執行引擎認為此時全表掃描更加合適。

推而廣之,or也是一樣的道理。其它> >= < <= BETWEEN AND應該也是同樣的道理。因為它們歸根結底都是范圍查詢。

  • or 的情況

圖片圖片

圖片圖片

圖片圖片

  • > <的情況

圖片圖片

圖片圖片

當然,總體來說,in后面條件越少越好,假設一張表有1000萬條數據,in后面的條件有10000個,這時候就算走了range索引,估計效率也好不到哪里。

責任編輯:武曉燕 來源: Shepherd進階筆記
相關推薦

2020-08-26 08:18:39

數據索引查詢

2018-10-22 08:14:04

2013-05-16 13:57:31

SNMP網絡運維管理

2012-03-13 09:59:50

小米科技雷軍

2022-12-20 07:39:46

2023-12-21 17:11:21

Containerd管理工具命令行

2011-08-08 09:35:30

云計算

2012-02-16 08:32:36

思科

2011-10-20 09:27:04

2017-03-16 15:28:20

人工智能視覺識別

2020-02-17 21:52:19

微信支付寶健康碼

2023-12-15 09:45:21

阻塞接口

2018-12-05 08:22:05

IPv6IPv4網絡

2019-11-14 16:23:07

MySQL索引數據庫

2021-03-25 11:15:27

數字化轉型IT技術

2010-04-28 16:26:31

程序員

2021-02-22 09:05:59

Linux字符設備架構

2021-06-04 09:35:05

Linux字符設備架構

2020-12-18 11:54:22

Linux系統架構

2009-09-14 09:40:48

微軟Linux代碼
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 一区二区三区不卡视频 | 国产精品99久久久久久www | 日本国产高清 | 欧美日批 | 成人一区二区三区在线观看 | 国产精品久久久久久中文字 | 日韩一区二区三区视频 | 久久久精品一区二区三区四季av | 夜夜爽99久久国产综合精品女不卡 | 啪视频在线 | 日本视频免费观看 | 在线免费观看黄视频 | 午夜在线 | 亚洲国产一区在线 | 亚洲综合字幕 | 国产成人午夜精品影院游乐网 | 欧美成人激情 | 黄片毛片| 欧美激情视频一区二区三区在线播放 | 国产1区2区3区 | 国产福利视频网站 | 羞羞视频在线网站观看 | 免费不卡视频 | 中文字幕第一页在线 | 日韩精品久久久久久 | 色眯眯视频在线观看 | 日韩成人在线视频 | 91视频日本 | 精品久久久久久红码专区 | 色综合桃花网 | 亚洲欧美在线一区 | www成人免费视频 | 国产激情自拍视频 | 国产亚洲一区二区三区在线观看 | 久久精品国产99国产精品 | 久久精品久久综合 | 自拍亚洲 | 国产欧美一区二区三区日本久久久 | 91精品国产91久久久 | 欧美综合自拍 | 四虎最新视频 |