gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区

站長資訊網
最全最豐富的資訊網站

count(*)為什么很慢?原因分析

count(*)為什么很慢?下面本篇文章就來給大家分析一下原因,并聊聊count(*)的執行過程,希望對大家有所幫助!

count(*)為什么很慢?原因分析

本沒想著寫這篇文章的,因為我覺得這個東西大多數有經驗的開發遇到過,肯定也了解過相關的原因,但最近我看到有幾個關注的技術公眾號在推送相關的文章。實在令我吃驚!

先上公眾號文章的結論:

  • count(*) :它會獲取所有行的數據,不做任何處理,行數加1。
  • count(1):它會獲取所有行的數據,每行固定值1,也是行數加1。
  • count(id):id代表主鍵,它需要從所有行的數據中解析出id字段,其中id肯定都不為NULL,行數加1。
  • count(普通索引列):它需要從所有行的數據中解析出普通索引列,然后判斷是否為NULL,如果不是NULL,則行數+1。
  • count(未加索引列):它會全表掃描獲取所有數據,解析中未加索引列,然后判斷是否為NULL,如果不是NULL,則行數+1。

結論:count(*) ≈ count(1) > count(id) > count(普通索引列) > count(未加索引列)

我也不想賣關子了,以上結論純屬放屁。根本就是個人yy出來的東西,甚至不愿意去驗證一下,哪怕看一眼執行計劃,也得不出這么離譜的結論。

我不敢相信這是一篇被多個技術公眾號轉載的文章!

以下所有的內容均是基于,mysql 5.7 + InnoDB引擎, 進行的分析。

拓展:

MyISAM 如果沒有查詢條件,只是簡單的統計表中數據總數,將會返回的超快,因為service層中獲取到表信息中的總行數是準確的,而InnoDB只是一個估值。

實例

廢話不多說,先看一個例子。

以下是一張表數據量有100w,表中字段相對較短,整體數據量不算大。

CREATE TABLE `hospital_statistics_data` (   `pk_id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵',   `id` varchar(36) COLLATE utf8mb4_general_ci NOT NULL COMMENT '外鍵',   `hospital_code` varchar(36) COLLATE utf8mb4_general_ci NOT NULL COMMENT '醫院編碼',   `biz_type` tinyint NOT NULL COMMENT '1服務流程  2管理效果',   `item_code` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '考核項目編碼',   `item_name` varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '考核項目名稱',   `item_value` varchar(36) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '考核結果',   `is_deleted` tinyint DEFAULT NULL COMMENT '是否刪除 0否 1是',   `gmt_created` datetime DEFAULT NULL COMMENT '創建時間',   `gmt_modified` datetime DEFAULT NULL COMMENT 'gmt_modified',   `gmt_deleted` datetime(3) DEFAULT '9999-12-31 23:59:59.000' COMMENT '刪除時間',   PRIMARY KEY (`pk_id`) ) DEFAULT CHARSET=utf8mb4  COMMENT='醫院統計數據';
登錄后復制

此表初始狀態只有一個聚簇索引

以下分不同索引情況,看一下COUNT(*)的執行計劃。

1)在只有一個聚簇索引的情況下看一下執行計劃。

EXPLAIN select COUNT(*) from hospital_statistics_data;
登錄后復制

登錄后復制

登錄后復制

結果:

count(*)為什么很慢?原因分析

關于執行計劃的各個參數的含義,不在本文的討論范圍內,可自行了解。

這里只關注以下幾個屬性。

  • type: 這里顯示index,說明使用了索引。

  • key:PRIMARY使用了主鍵索引。

  • key_len: 索引長度8字節。

這里有很關鍵的一點:count(*)也會走索引,在當前情況下使用了聚簇索引。

好,再往下看。

2)存在一個非聚簇索引(二級索引)

給表添加一個hospital_code索引。

alter table hospital_statistics_data add index idx_hospital_code(hospital_code)
登錄后復制

此時表中存在2個索引,主鍵 hospital_code

同樣的,再執行一下:

EXPLAIN select COUNT(*) from hospital_statistics_data;
登錄后復制

登錄后復制

登錄后復制

結果:

count(*)為什么很慢?原因分析

同樣的,看一下 type、key和key_len三個字段。

是不是覺得有點“神奇”。

為何索引變成剛添加的idx_hospital_code了。

先別急著想結論,再看下面一種情況。

3)存在兩個非聚簇索引(二級索引)

在上面的基礎上,再添加一個二級索引。

alter table hospital_statistics_data add index idx_biz_type(biz_type)
登錄后復制

此時表中存在3個索引,主鍵 、hospital_code 和 biz_type。

同樣的,執行一下:

EXPLAIN select COUNT(*) from hospital_statistics_data;
登錄后復制

登錄后復制

登錄后復制

結果:

count(*)為什么很慢?原因分析

是不是更困惑了,索引又..又又…變了.

變成新添加的idx_biz_type。

先不說為何會產生以上的變化,繼續往下分析。

在以上3個索引的基礎上,分別看一下,count(1)count(id)count(index)count(無索引)

這4種情況,與count(*)的執行計劃有何區別。

  • count(1)

count(*)為什么很慢?原因分析

  • count(id) 對于樣例表來說是,主鍵是pk_id

count(*)為什么很慢?原因分析

  • count(index)

這里選取biz_type索引字段。

count(*)為什么很慢?原因分析

  • count(無索引)

count(*)為什么很慢?原因分析

小結:

  • count(index) 會使用當前index指定的索引。

  • count(無索引) 是全表掃描,未走索引。

  • count(1) , count(*), count(id) 一樣都會選擇idx_biz_type索引

看到這,你還覺得那些千篇一律的公眾號文章的結論正確嗎?

必要知識點

  • mysql 分為service層引擎層

  • 所有的sql在執行前會經過service層的優化,優化分為很多類型,簡單的來說可分為成本規則

  • 執行計劃所反映的是service層經過sql優化后,可能的執行過程。并非絕對(免得有些人說我只看執行計劃過于片面)。絕大多數情況執行計劃是可信的

  • 索引類型分為聚簇索引非聚簇索引(二級索引)。其中數據都是掛在聚簇索引上的,非聚簇索引上只是記錄的主鍵id。

  • 拋開數據內存,只談數據量,都是扯淡。什么500w就是極限,什么2個表以上的join都需要優化了,什么is null不會走索引等,純純的放屁。

  • 相信一點,編寫mysql代碼的人比,看此文章的大部分人都要優秀。他們會盡可能在執行前,對我這樣菜逼寫的亂七八糟的sql進行優化。

原因分析

其實原因非常非常簡單,上面也說了,service層會基于成本進行優化

并且,正常情況下,非聚簇索引所占有的內存要遠遠小于聚簇索引。所以問題來了,如果你是mysql的開發人員,你在執行count(*)查詢的時候會使用那個索引?

我相信正常人都會使用非聚簇索引

那如果存在2個甚至多個非聚簇索引又該如何選擇呢?

那肯定選擇最短的,占用內存最小的一個呀,在回頭看看上面的實例,還迷惑嗎。

同樣都是非聚簇索引。idx_hospital_codelen146字節;而idx_biz_typelen只有1。那還要選嗎?

那為何count(*)走了索引,卻還是很慢呢?

這里要明確一點,索引只是提升效率的一種方式,但不能完全的解決效率問題。count(*)有一個明顯的缺陷,就是它要計算總數,那就意味著要遍歷所有符合條件的數據,相當于一個計數器,在數據量足夠大的情況下,即使使用非聚簇索引也無法優化太多。

官方文檔:

InnoDBhandlesSELECT COUNT(*)andSELECT COUNT(1)operations in the same way. There is no performance difference.

簡單的來說就是,InnoDB下 count(*) 等價于 count(1)

既然會自動走索引,那么上面那個所謂的速度排序還覺得對嗎? count(*)的性能跟數據量有很大的關系,此外最好有一個字段長度較短的二級索引。

拓展:

另外,多說一下,關于網上說的那些索引失效的情況,大多都是片面的,我這里只說一點。量變才能引起質變,索引的失效取決于你圈定數據的范圍,若你圈定的數據量占整體數據量的比例過高,則會放棄使用索引,反之則會優先使用索引。但是此規則并不是完美的,有時候可能與你預期的不同,也可以通過一些技巧強制使用索引,但這種方式少用。

舉個栗子:

通過上面這個表hospital_statistics_data,我進行了如下查詢:

select * from hospital_statistics_data where hospital_code is not null;
登錄后復制

此時這個sql會使用到hospital_code的索引嗎?

這里也不賣關子了,若hospital_code只有很少一部分數據是null值,那么將不會走索引,反之則走索引。

原因就2個字:回表

好比去買砂糖橘,如果你只買幾斤,那么你隨便挑筐里面好的就行。但是如果你要買一筐,我相信老板不會讓你在里面一個個挑,而是一次給你一整筐,當然大家都不傻,都知道筐里里面肯定有那么幾個壞果子。但是這樣效率最高,而且對老板來說損失更小。

執行過程

摘抄自《從根上理解mysql》。我強烈推薦沒有系統學過mysql的,看看這本書。

1.首先在server層維護一個count變量

2.server層向InnoDB引擎要第一條記錄

3.InnoDB找到第一條二級索引記錄,并返回給server層(注意:由于此時只是統計記錄數量,所以并不需要回表)

4.由于COUNT函數的參數是*,MySQL會將*當作常數0處理。由于0并不是NULL,server層給count變量加1。

5.server層向InnoDB要下一條記錄。

6.InnoDB通過二級索引記錄的next_record屬性找到下一條二級索引記錄,并返回給server層。

7.server層繼續給count變量加1。

8.重復上述過程,直到InnoDB向server層返回沒記錄可查的消息。

9.server層將最終的count變量的值發送到客戶端。

總結

寫完后還是心中挺郁悶的,現在能從公眾號獲取到的好文章越來越少了,現在已經是知識付費的時代了。

挺懷念剛工作的時候,那時候每天上午都花點時間看看公眾號文章,現在全都是廣告。哎!

不過也正常,誰也不能一直為愛發電。

學習還是建議多看看書籍,一般能成書的都不會太差。現在晚上能搜到的都是千篇一律的文章,對錯不知。網上

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
gmnon.cn-疯狂蹂躏欧美一区二区精品,欧美精品久久久久a,高清在线视频日韩欧美,日韩免费av一区二区
丝袜老师办公室里做好紧好爽| 可以在线看的av网站| 免费毛片网站在线观看| 成人一区二区av| 国产色视频在线播放| 国产在线播放观看| 少妇高清精品毛片在线视频| 91精品国产吴梦梦| 亚洲综合在线一区二区| 一区二区xxx| 水蜜桃在线免费观看| www.黄色网址.com| 久久久久久香蕉| 2021国产视频| jizz18女人| 国产欧美日韩小视频| 久久精品久久99| 又大又硬又爽免费视频| 一道本在线免费视频| 黄色网址在线免费看| 国产福利精品一区二区三区| 91制片厂免费观看| 999精品视频在线| 少妇网站在线观看| wwwwww欧美| 丰满少妇被猛烈进入高清播放| 午夜精品久久久久久久无码| 国产一级片中文字幕| 女女百合国产免费网站| av免费看网址| av在线免费看片| 能在线观看的av| 粉嫩虎白女毛片人体| 成人综合视频在线| 免费拍拍拍网站| 亚洲无吗一区二区三区| www.色就是色| 国产精品久久久久久久av福利| 樱花草www在线| 五月天婷婷影视| 国产aaa免费视频| 九一国产精品视频| av片中文字幕| 妞干网在线免费视频| 妓院一钑片免看黄大片| 国产中文字幕在线免费观看| 亚洲综合av在线播放| 国产一区二区视频播放| 日本少妇高潮喷水视频| 精品少妇在线视频| 人妻少妇精品无码专区二区| 国产a级一级片| 亚洲免费在线播放视频| 欧美人成在线观看| 毛毛毛毛毛毛毛片123| 最新av在线免费观看| 深夜黄色小视频| 日日干日日操日日射| 亚洲激情在线看| av免费一区二区| 欧美黄网在线观看| 全黄性性激高免费视频| 女人喷潮完整视频| 午夜宅男在线视频| 免费日韩在线观看| 成人免费观看在线| 久久久999免费视频| 性欧美在线视频| 91免费视频黄| 免费观看黄色的网站| 五月六月丁香婷婷| 超碰影院在线观看| 丁香六月激情网| 在线播放 亚洲| 亚洲免费黄色录像| 咪咪色在线视频| www亚洲国产| 路边理发店露脸熟妇泻火| 国产在线拍揄自揄拍无码| 三级a三级三级三级a十八发禁止| 久久无码高潮喷水| 午夜视频在线网站| 麻豆视频传媒入口| 欧美日韩中文字幕在线播放| 性久久久久久久久久久久久久| 日韩精品在线播放视频| 97视频在线免费| 人妻激情另类乱人伦人妻| 国产午夜大地久久| 日日噜噜夜夜狠狠久久丁香五月| 亚洲精品一二三四五区| 亚洲小说欧美另类激情| 热99这里只有精品| a级黄色片免费| 国产永久免费网站| 毛片在线视频观看| 欧美两根一起进3p做受视频| 日本午夜激情视频| 国产素人在线观看| 欧美美女黄色网| www.成年人| 欧美日韩视频免费| 亚洲一级片av| 手机在线免费毛片| 欧美成人福利在线观看| 91精品91久久久中77777老牛| 熟妇人妻va精品中文字幕| 久久国产精品视频在线观看| 欧美 日韩 国产在线观看| 亚洲黄色a v| 日本a在线天堂| 欧美 日本 亚洲| aaa毛片在线观看| 欧美日韩黄色一级片| 男女啪啪免费观看| 亚洲一区 在线播放| 成人毛片视频网站| 日韩中文在线字幕| 亚洲xxx在线观看| 在线观看视频黄色| 免费无码不卡视频在线观看| 99久久久精品视频| av片中文字幕| 亚洲精品一二三四五区| 在线免费看v片| 免费一区二区三区在线观看| 1024av视频| 欧美精品一区二区三区免费播放| 性chinese极品按摩| 亚洲欧美日韩网站| 欧美伦理视频在线观看| 麻豆tv在线播放| 在线视频观看一区二区| 国产精品wwwww| 九九久久九九久久| 男人天堂网视频| 欧美另类videosbestsex日本| 黄色一级视频在线播放| 性高湖久久久久久久久aaaaa| 日韩视频免费在线播放| 久久无码高潮喷水| 特级西西人体www高清大胆| 路边理发店露脸熟妇泻火| 成年人网站免费视频| 波多野结衣xxxx| 可以看毛片的网址| 国内自拍中文字幕| 亚洲自拍第三页| 狠狠97人人婷婷五月| 欧美一级特黄aaaaaa在线看片| 国产极品粉嫩福利姬萌白酱| www.射射射| 国产原创精品在线| 欧美午夜性视频| 欧美一区二区三区爽大粗免费 | 欧美日韩在线视频一区二区三区| 中文字幕中文在线| 亚洲欧美天堂在线| 国产91在线亚洲| 鲁一鲁一鲁一鲁一av| 九色porny91| 日韩毛片在线免费看| 91精品国产91久久久久麻豆 主演| 手机在线视频你懂的| 大陆极品少妇内射aaaaa| 欧洲美女和动交zoz0z| 成人在线观看www| 美女网站免费观看视频| 搡的我好爽在线观看免费视频| 四虎4hu永久免费入口| 91人人澡人人爽人人精品| 六月丁香婷婷在线| 51xx午夜影福利| 日韩中文字幕a| 国产成人av影视| 国产a视频免费观看| 两性午夜免费视频| 国产不卡的av| 国产高清av在线播放| 久久久久国产精品熟女影院| 日韩欧美理论片| www.久久av.com| 一区二区三区入口| 免费看av软件| 日本中文字幕观看| 日本福利视频在线观看| 一级做a免费视频| 黄瓜视频免费观看在线观看www| 日韩中字在线观看| 国产偷人视频免费| 久久99999| 中文字幕第一页在线视频| 欧美 日韩 国产一区| 中文字幕亚洲影院| 午夜激情在线观看视频| 国产a级片免费看| 亚洲精品少妇一区二区| 中文字幕综合在线观看| av动漫在线播放| 欧美视频亚洲图片|