日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

腾讯面试:一条SQL语句执行得很慢的原因有哪些?

發布時間:2024/9/27 数据库 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 腾讯面试:一条SQL语句执行得很慢的原因有哪些? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

戳藍字“CSDN云計算”關注我們哦!

技術頭條:干貨、簡潔、多維全面。更多云計算精華知識盡在眼前,get要點、solve難題,統統不在話下!

??

作者:帥地

轉自:苦逼的碼農


說實話,這個問題可以涉及到?MySQL?的很多核心知識,可以扯出一大堆,就像要考你計算機網絡的知識時,問你“輸入URL回車之后,究竟發生了什么”一樣,看看你能說出多少了。

之前騰訊面試的實話,也問到這個問題了,不過答的很不好,之前沒去想過相關原因,導致一時之間扯不出來。所以今天,我帶大家來詳細扯一下有哪些原因,相信你看完之后一定會有所收獲,不然你打我。

一、開始裝逼:分類討論

一條?SQL?語句執行的很慢,那是每次執行都很慢呢?還是大多數情況下是正常的,偶爾出現很慢呢?所以我覺得,我們還得分以下兩種情況來討論。

1、大多數情況是正常的,只是偶爾會出現很慢的情況。

2、在數據量不變的情況下,這條SQL語句一直以來都執行的很慢。

針對這兩種情況,我們來分析下可能是哪些原因導致的。

二、針對偶爾很慢的情況

一條?SQL?大多數情況正常,偶爾才能出現很慢的情況,針對這種情況,我覺得這條SQL語句的書寫本身是沒什么問題的,而是其他原因導致的,那會是什么原因呢?

1、數據庫在刷新臟頁我也無奈啊

當我們要往數據庫插入一條數據、或者要更新一條數據的時候,我們知道數據庫會在內存中把對應字段的數據更新了,但是更新之后,這些更新的字段并不會馬上同步持久化到磁盤中去,而是把這些更新的記錄寫入到 redo log 日記中去,等到空閑的時候,在通過 redo log 里的日記把最新的數據同步到磁盤中去。

不過,redo log 里的容量是有限的,如果數據庫一直很忙,更新又很頻繁,這個時候 redo log 很快就會被寫滿了,這個時候就沒辦法等到空閑的時候再把數據同步到磁盤的,只能暫停其他操作,全身心來把數據同步到磁盤中去的,而這個時候,就會導致我們平時正常的SQL語句突然執行的很慢,所以說,數據庫在在同步數據到磁盤的時候,就有可能導致我們的SQL語句執行的很慢了。

2、拿不到鎖我能怎么辦

這個就比較容易想到了,我們要執行的這條語句,剛好這條語句涉及到的,別人在用,并且加鎖了,我們拿不到鎖,只能慢慢等待別人釋放鎖了。或者,表沒有加鎖,但要使用到的某個一行被加鎖了,這個時候,我也沒辦法啊。

如果要判斷是否真的在等待鎖,我們可以用?show processlist這個命令來查看當前的狀態哦,這里我要提醒一下,有些命令最好記錄一下,反正,我被問了好幾個命令,都不知道怎么寫,呵呵。

下來我們來訪分析下第二種情況,我覺得第二種情況的分析才是最重要的

三、針對一直都這么慢的情況

如果在數據量一樣大的情況下,這條?SQL?語句每次都執行的這么慢,那就就要好好考慮下你的?SQL?書寫了,下面我們來分析下哪些原因會導致我們的?SQL?語句執行的很不理想。

我們先來假設我們有一個表,表里有下面兩個字段,分別是主鍵?id,和兩個普通字段?c?和?d。

mysql>?CREATE?TABLE?`t`?(
??`id`?int(11)?NOT?NULL,
??`c`?int(11)?DEFAULT?NULL,
??`d`?int(11)?DEFAULT?NULL,
??PRIMARY?KEY?(`id`)
)?ENGINE=InnoDB;

1、扎心了,沒用到索引

沒有用上索引,我覺得這個原因是很多人都能想到的,例如你要查詢這條語句

select?*?from?t?where?100?<c?and?c?<?100000;

(1)、字段沒有索引

剛好你的?c?字段上沒有索引,那么抱歉,只能走全表掃描了,你就體驗不會索引帶來的樂趣了,所以,這回導致這條查詢語句很慢。

(2)、字段有索引,但卻沒有用索引

好吧,這個時候你給 c 這個字段加上了索引,然后又查詢了一條語句

select?*?from?t?where?c?-?1?=?1000;

我想問大家一個問題,這樣子在查詢的時候會用索引查詢嗎?

答是不會,如果我們在字段的左邊做了運算,那么很抱歉,在查詢的時候,就不會用上索引了,所以呢,大家要注意這種字段上有索引,但由于自己的疏忽,導致系統沒有使用索引的情況了。

正確的查詢應該如下

select?*?from?t?where?c?=?1000?+?1;

有人可能會說,右邊有運算就能用上索引?難道數據庫就不會自動幫我們優化一下,自動把?c?-?1=1000?自動轉換為?c?=?1000+1。

不好意思,確實不會幫你,所以,你要注意了。

(3)、函數操作導致沒有用上索引

如果我們在查詢的時候,對字段進行了函數操作,也是會導致沒有用上索引的,例如

select?*?from?t?where?pow(c,2)?=?1000;

這里我只是做一個例子,假設函數?pow?是求?c?的?n?次方,實際上可能并沒有?pow(c,2)這個函數。其實這個和上面在左邊做運算也是很類似的。

所以呢,一條語句執行都很慢的時候,可能是該語句沒有用上索引了,不過具體是啥原因導致沒有用上索引的呢,你就要會分析了,我上面列舉的三個原因,應該是出現的比較多的吧。


2、呵呵,數據庫自己選錯索引了

我們在進行查詢操作的時候,例如

select?*?from?t?where?100?<?c?and?c?<?100000;

我們知道,主鍵索引和非主鍵索引是有區別的,主鍵索引存放的值是整行字段的數據,而非主鍵索引上存放的值不是整行字段的數據,而且存放主鍵字段的值。不大懂的可以看我這篇文章:面試小知識:MySQL索引相關?? ?里面有說到主鍵索引和非主鍵索引的區別

也就是說,我們如果走?c?這個字段的索引的話,最后會查詢到對應主鍵的值,然后,再根據主鍵的值走主鍵索引,查詢到整行數據返回。

好吧扯了這么多,其實我就是想告訴你,就算你在?c?字段上有索引,系統也并不一定會走?c?這個字段上的索引,而是有可能會直接掃描掃描全表,找出所有符合?100?<?c?and?c?<?100000?的數據。

為什么會這樣呢?

其實是這樣的,系統在執行這條語句的時候,會進行預測:究竟是走?c?索引掃描的行數少,還是直接掃描全表掃描的行數少呢?顯然,掃描行數越少當然越好了,因為掃描行數越少,意味著I/O操作的次數越少。

如果是掃描全表的話,那么掃描的次數就是這個表的總行數了,假設為?n;而如果走索引?c?的話,我們通過索引?c?找到主鍵之后,還得再通過主鍵索引來找我們整行的數據,也就是說,需要走兩次索引。而且,我們也不知道符合?100?c?<?and?c?<?10000?這個條件的數據有多少行,萬一這個表是全部數據都符合呢?這個時候意味著,走?c?索引不僅掃描的行數是?n,同時還得每行數據走兩次索引。

所以呢,系統是有可能走全表掃描而不走索引的。那系統是怎么判斷呢?

判斷來源于系統的預測,也就是說,如果要走?c?字段索引的話,系統會預測走?c?字段索引大概需要掃描多少行。如果預測到要掃描的行數很多,它可能就不走索引而直接掃描全表了。

那么問題來了,系統是怎么預測判斷的呢?這里我給你講下系統是怎么判斷的吧,雖然這個時候我已經寫到脖子有點酸了。

系統是通過索引的區分度來判斷的,一個索引上不同的值越多,意味著出現相同數值的索引越少,意味著索引的區分度越高。我們也把區分度稱之為基數,即區分度越高,基數越大。所以呢,基數越大,意味著符合?100?<?c?and?c?<?10000?這個條件的行數越少。

所以呢,一個索引的基數越大,意味著走索引查詢越有優勢。

那么問題來了,怎么知道這個索引的基數呢?

系統當然是不會遍歷全部來獲得一個索引的基數的,代價太大了,索引系統是通過遍歷部分數據,也就是通過采樣的方式,來預測索引的基數的。

扯了這么多,重點的來了,居然是采樣,那就有可能出現失誤的情況,也就是說,c?這個索引的基數實際上是很大的,但是采樣的時候,卻很不幸,把這個索引的基數預測成很小。例如你采樣的那一部分數據剛好基數很小,然后就誤以為索引的基數很小。然后就呵呵,系統就不走 c 索引了,直接走全部掃描了

所以呢,說了這么多,得出結論:由于統計的失誤,導致系統沒有走索引,而是走了全表掃描,而這,也是導致我們?SQL?語句執行的很慢的原因。

這里我聲明一下,系統判斷是否走索引,掃描行數的預測其實只是原因之一,這條查詢語句是否需要使用使用臨時表、是否需要排序等也是會影響系統的選擇的。

不過呢,我們有時候也可以通過強制走索引的方式來查詢,例如

select?*?from?t?force?index(a)?where?c?<?100?and?c?<?100000;

我們也可以通過

show?index?from?t;

來查詢索引的基數和實際是否符合,如果和實際很不符合的話,我們可以重新來統計索引的基數,可以用這條命令

analyze?table?t;

來重新統計分析。

既然會預測錯索引的基數,這也意味著,當我們的查詢語句有多個索引的時候,系統有可能也會選錯索引哦,這也可能是?SQL?執行的很慢的一個原因。

好吧,就先扯這么多了,你到時候能扯出這么多,我覺得已經很棒了,下面做一個總結。

四、總結

以上是我的總結與理解,最后一個部分,我怕很多人不大懂數據庫居然會選錯索引,所以我詳細解釋了一下,下面我對以上做一個總結。

一個?SQL?執行的很慢,我們要分兩種情況討論:

1、大多數情況下很正常,偶爾很慢,則有如下原因

(1)、數據庫在刷新臟頁,例如?redo?log?寫滿了需要同步到磁盤。

(2)、執行的時候,遇到鎖,如表鎖、行鎖。

2、這條?SQL?語句一直執行的很慢,則有如下原因。

(1)、沒有用上索引:例如該字段沒有索引;由于對字段進行運算、函數操作導致無法用索引。

(2)、數據庫選錯了索引。

大家如果有補充的,也是可以留言區補充一波哦。



福利

掃描添加小編微信,備注“姓名+公司職位”,加入【云計算學習交流群】,和志同道合的朋友們共同打卡學習!



推薦閱讀:

  • 10 種最流行的 Web 挖掘工具 | 程序員硬核評測

  • 《復聯4》| 生活需要漫威這塊糖

  • 如何向 6 歲的孩子解釋編程?這個解釋厲害了

  • “踏實工作 7 年,辭職時老板頭都不抬”

  • 60倍回報! AI工程師用OpenAI創建了一個比特幣自動交易工具! 這里是詳細做法 | 技術頭條

  • 賭5毛錢,你解不出這道Google面試題


真香,朕在看了!

總結

以上是生活随笔為你收集整理的腾讯面试:一条SQL语句执行得很慢的原因有哪些?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久亚洲av午夜福利精品一区 | a√在线| 日本久久一级片 | 精品一区二区在线播放 | 日本精品视频在线观看 | 麻豆一区二区三区 | 日韩中文字幕视频在线观看 | a毛片在线| 久久艹综合 | 久久精品999 | 天天操婷婷 | 成人深夜免费视频 | 无码久久精品国产亚洲av影片 | 国产精品无码网站 | 久久久久亚洲av无码专区体验 | 国产福利91 | 9999热视频| 成人人伦一区二区三区 | 超碰在线免费看 | 亚洲风情亚aⅴ在线发布 | 日韩美女在线视频 | 最新色站 | 天天操女人 | 野战少妇38p | 99久久免费看精品国产一区 | 亚洲一区二区三区免费在线观看 | 特黄色一级片 | 亚州精品国产精品乱码不99按摩 | 国产女主播自拍 | 精品久久久影院 | 国产视频一区二区三区四区五区 | 国产精品三级 | 久久久人| 免费久久久 | 午夜淫片| 青草视频在线观看视频 | 亚洲v国产| 色眯眯av | av在线资源观看 | 风韵多水的老熟妇 | 性一交一乱一色一免费无遮挡 | 国外av在线 | 久久久久久久久久久久久久 | 精品无码人妻少妇久久久久久 | 毛片在线网 | 黄色在线不卡 | 国产综合精品视频 | 久久综合成人网 | 成年人免费网站 | 亚洲综合色在线观看 | 亚洲二区精品 | 国产九九精品视频 | 国产一级在线播放 | 亚洲中文字幕一区二区 | 免费黄色av网址 | 亚洲成人乱码 | 欧美一区免费看 | 午夜av剧场 | 免费av影视| 天堂av免费在线观看 | 国产精品一区二区在线 | 亚洲高清视频一区二区 | 看国产毛片 | 成人免费在线视频 | av免费网| 亚洲一区精品在线 | 国产做爰免费观看视频 | 狠狠操网址 | 国内精品国产三级国产aⅴ久 | 久久综合网址 | 五十路熟母 | 亚洲欧美日韩在线 | 在线免费看av片 | 成人毛片视频网站 | 亚洲精品www久久久久久广东 | 光棍影院一区二区 | 综合视频一区 | 国产精选av| 特黄aaaaaaaaa毛片免 | 久久久久久91亚洲精品中文字幕 | 久久久久激情 | 91精品国产91久久久久福利 | 天天综合网天天综合色 | 美国伊人网 | 日韩精品片 | 亚洲国产一区二区三区四区 | 人体私拍套图hdxxxx | 色综合网站 | 色吧在线观看 | 欧美色呦呦 | 国产精品videossex国产高清 | 久久久精品人妻无码专区 | 国产免费美女 | 国产在线观看av | 清纯唯美亚洲综合 | 成年网站 | 国产精品不卡 | 白白色在线观看 | 亚洲啪啪av |