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

明明加了索引,為什么查詢還是慢?

原創
運維 數據庫運維
小李今天剛上班就收到客戶的反饋,說查詢用戶信息會非常的慢,有時甚至會出現超時的現象。

【51CTO.com原創稿件】小李今天剛上班就收到客戶的反饋,說查詢用戶信息會非常的慢,有時甚至會出現超時的現象。

[[349161]]

圖片來自 Pexels 

小李這就納悶了分明已經給表加上了索引為什么還這么慢呢。小李分析了好久都沒分析出原因,于是只能找到同部門的掃地僧大林子。

大林子一邊聽著小李的描述一邊看著項目,就在小李剛把問題描述完大林子就對小李說:“問題解決了”,小李震驚不已,問道:“這么 6,是什么原因導致的呢?分明我已經加了索引了啊?”

大林子說:“這是很多開發人員很容易忽視的問題......”聽完大林子的講解小李瞬間茅塞頓開。那么具體什么原因呢,下面我就給大家講解一下。

原因講解

首先,我們來創建一個存儲引擎為 InnoDB 的 User 表,這個表包含三個字段分別是 id,name 和 age。

其中 id 為主鍵 name 上添加了一個普通索引名字叫 n,接著我們像這條表中插入 10 億條數據。

表和數據都創建完了,下面我們就來說說為什么加上了索引還是查詢很慢,以及解決方案。

MySQL 會根據語句的執行時間來判斷 SQL 語句是否是慢查詢語句。

當一個 SQL 語句在執行時,MySQL 把語句執行時間和系統參數 long_query_time(這個參數的默認值是 10 秒,但是在實際項目中我們會將這個參數值設置為1秒甚至更短的時間) 作比較。

如果執行時間大于這個參數的值,那么就把這個語句記錄到慢查詢日志中。那么在語句執行過程中我們如何得知是否使用了索引呢?

這時我們就可以使用 explain 語句來查看數據結果中 Key 的值是否 null ,如果是 null 則說明沒有使用索引。

下面我們來看一個例子:

  1. explain select * from user
  2. explain select * from user where id=1; 
  3. explain select name from user

上面三個 explain 語句返回的 key 如下表所示:

 

從上表我們可以看出第一個語句沒有使用索引,第二個使用了主鍵索引,第三個語句使用 n 這個索引。

我們的 user 表有 10 億條數據,可想而知第一條查詢語句執行效率肯定低,第二個查詢語句看似執行效率高,其實在極端環境下(比如 CPU 高負載)也會出現查詢效率低的問題。

最后一個查詢語句呢雖然使用了 n 這個索引,但是它實際上執行了掃描整個索引樹的操作,因此查詢效率也高不到哪去。

綜上所述,我們可知索引是否使用和是否被記錄到慢查詢中幾乎沒有聯系,索引只是 SQL 的一個執行過程,SQL 的執行時間才是決定是否被記錄到慢查詢中的關鍵。

前面一小節我們只是簡單的分析了一下問題,下面我們進一步看這個問題。我們知道 InnoDB 是索引組織表,所有數據都存儲在索引樹上。

 

在 InnoDB 中數據放在主鍵索引里,因此理論上來說所有在 InnoDB 表中的查詢至少使用了一個索引。

比如這個 SQL 查詢語句 select * from user where id > 1000,很明顯它使用主鍵索引,并且這個語句一定執行了整個索引樹的掃描。

在 InnoDB 中只有一種情況叫不使用索引,就是從主鍵索引的最左邊的葉子結點開始向右掃描整個索引樹。

到目前為止我們已經知道了全索引掃描會造成查詢變慢,下面我們就來說一下另一個知識點過濾性 。

假如我們要查詢 user 表中 age 在 70 歲以上 80 歲以下的人員信息,你一定會在 age 字段上加入索引來避免全局掃描。

不錯,這是個好的想法,但是當你運行查詢語句時就會發現它依然執行的很慢,這是為什么呢?

 

要解答這個問題我們先來看一下 SQL 查詢語句的執行流程:

  • 搜索 age 索引樹,獲取到第一個 age 為 70 的記錄。
  • 拿到主鍵值,根據主鍵值去主鍵索引樹上獲取對應的信息,并將信息加入結果集。
  • 在 age 索引樹上向右側掃描,獲取到下一個主鍵值,執行第二部的操作。
  • 不斷執行上面的步驟,直到遇到第一個 age 大于 80 的記錄為止。

從上面的步驟中我們可以看出雖然使用了索引,但是查詢過程中掃描了上萬行甚至上億行。

因此我們可以得出結論:對于這種數據非常多的表,我們所要做的不僅僅是加入索引,還要保證索引的過濾性足夠優秀。

假如說我們把索引的過濾性也處理好了,是不是查詢時要掃描的行數就一定會表少呢?

這個答案是否定的,比如說我們的 user 表中的 name 和 age 字段共同組成了聯合索引并處理好了過濾性,這時當我們查詢姓李的并且年齡是 60 歲的數據時查詢效率依然很低。

 

我們先來看一下查詢語句的執行流程:

  • 首先從聯合索引上找到姓名字段是李字開頭的數據記錄。
  • 拿到主鍵值,根據主鍵值在主鍵索引書上去除匹配的數據。
  • 接著根據 age 字段去判斷年齡是否等于 60,如果符合就加入結果集。
  • 然后再聯合所以上向右側遍歷,并不斷做回表和判斷,直到遇到 name 的第一個字不是李的為止。

Tip:所謂的回表就是根據主鍵值去主鍵索引樹上查找對應的數據。

從上面的步驟中我們可以看出最耗時的就是回表,如果姓李的數據有 2 億條那么就要回表 2 億次,并且 SQL 在定位第一行數據時只能使用最左前綴原則。

這種耗時的回表操作步驟在 MySQL 5.6 及其以后的版本中已經做了 index condition pushdown 優化。

優化后的流程很簡單:

  • 首先從聯合索引上找到姓名字段是李字開頭的數據記錄,并判斷這個記錄里 age 是不是 60,如果是就執行回表取出數據假如結果集。
  • 重復步驟1,直到配當第一個字不是李字的記錄為止。

優化后和優化前的區別是把 age 的對比步驟放在了遍歷聯合索引樹上,減少了回表次數。

但是雖然減少了回表次數,聯合索引樹的遍歷去沒有減少依然要遍歷 2 億次,那么有沒有更好的優化方案呢?答案是有的,我們可以實虛擬列來進行處理。

首先我們需要把 name 的第一個字和 age 做一個聯合索引,讓虛擬列的值總是等于 name 字段的前兩個字節,這里需要注意的是虛擬列不隨著 insert 和 update 變化,它的值是自定義生成的。

語句如下:

  1. alter table user add name_first varchar(2) generated (left(name,1)),add index(name_first,age); 

經過上述的優化后聯合索引樹的查詢次數也降低了,本質上就是創建一個緊湊的索引加快查詢。

總結

這篇文章主要介紹了查詢優化的基本思路,只要記住優化查詢的過程都是減少掃描行數的過程,就可以做到在 SQL 查詢面前百戰百勝。

作者:朱鋼,筆名喵叔

簡介:.NET 高級開發人員,2019 年度博客之星 20 強,長期從事電子政務系統和AI客服系統的設計與開發,目前就職于國內某 BIM 大廠從事招投標軟件的開發。

編輯:陶家龍

征稿:有投稿、尋求報道意向技術人請聯絡 editor@51cto.com

【51CTO原創稿件,合作站點轉載請注明原文作者和出處為51CTO.com】

 

責任編輯:武曉燕 來源: 51CTO技術棧
相關推薦

2022-08-04 08:22:49

MySQL索引

2025-06-12 03:25:00

2020-03-05 16:55:56

索引數據庫SQL

2020-08-10 11:20:59

索引MySQL數據庫

2024-08-19 09:43:00

2021-06-28 07:13:35

SQL語句索引

2021-06-11 09:33:33

索引SQL語句

2020-01-22 16:36:52

MYSQL開源數據庫

2020-11-27 06:58:24

索引

2024-12-02 08:01:47

加鎖高并發程序

2018-08-16 08:03:21

Python語言解釋器

2024-04-15 04:00:00

C#反射代碼

2015-07-08 14:47:56

JSPBeetl

2022-07-20 07:32:46

Prototypevalue?容器

2016-12-28 11:28:19

.NET反射

2021-05-29 06:23:47

webpack esbuild

2020-08-14 09:11:29

RedisQPS數據庫

2025-05-28 01:10:00

SQL索引MySQL

2021-02-07 10:17:22

項目架構技術管理

2024-03-29 08:10:43

索引失效SQL
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲精品一区二区三区在线 | 国产日产精品一区二区三区四区 | 欧美日韩视频在线第一区 | 欧美在线视频一区二区 | 91久久久久 | 男女羞羞视频在线免费观看 | 国产成人a亚洲精品 | 玖玖国产 | 成人精品在线 | 日本成人中文字幕 | 国产精品久久久久久久模特 | 亚洲欧洲视频 | 亚洲精品视频一区 | 黑人粗黑大躁护士 | 91传媒在线观看 | 青青草在线视频免费观看 | 欧美日韩三级 | 视频在线一区 | 伊人伊成久久人综合网站 | av夜夜操 | 国产传媒在线观看 | 欧美美女一区二区 | 久久人人爽人人爽 | 亚洲国产精品激情在线观看 | 精品一区二区三区在线观看 | 婷婷色国产偷v国产偷v小说 | 国产免费一区二区三区最新6 | 欧美福利精品 | www.狠狠干| 九九综合| 成年免费大片黄在线观看岛国 | 日韩在线看片 | 精品一区在线看 | 一区二区三区四区在线视频 | 成人精品鲁一区一区二区 | 欧美国产91 | 国产日韩在线观看一区 | 久久久久久国产精品免费免费 | 精品国产乱码久久久久久丨区2区 | 天堂一区二区三区 | 久久久免费毛片 |