MySQL 筆記整理(5) --深入淺出索引(下)

来源:https://www.cnblogs.com/dogtwo0214/archive/2019/02/28/10451920.html
-Advertisement-
Play Games

筆記記錄自林曉斌(丁奇)老師的《MySQL實戰45講》 5) --深入淺出索引(下) 這次的筆記從一個簡單的查詢開始: 建表語句是這樣的 如果要執行 select * from T where k between 3 and 5這條語句,需要執行幾次搜索操作呢,會掃描多少行呢?由上面的建表及初始化語 ...


筆記記錄自林曉斌(丁奇)老師的《MySQL實戰45講》

5) --深入淺出索引(下)

  這次的筆記從一個簡單的查詢開始:

  建表語句是這樣的

mysql> create table T (
ID int primary key,
k int NOT NULL DEFAULT 0, 
s varchar(16) NOT NULL DEFAULT '',
index k(k))
engine=InnoDB;

insert into T values(100,1, 'aa'),(200,2,'bb'),(300,3,'cc'),(500,5,'ee'),(600,6,'ff'),(700,7,'gg');

  如果要執行 select * from T where k between 3 and 5這條語句,需要執行幾次搜索操作呢,會掃描多少行呢?由上面的建表及初始化語句我們很容易可以看出,表T上有ID欄位的主鍵索引,也有K欄位上的非主鍵索引。數據中滿足條件K在3和5之間的記錄有兩條,分別是 (300,3,'cc'),(500,5,'ee')。我們在K欄位上創建了索引,所以在執行這條語句時,MySQL就會使用這個索引。如果你看了我上篇筆記的話應該知道,K上的索引是非主鍵索引,而非主鍵索引存儲的其實是主鍵的值。所以這條語句的執行流程大致是下麵這個樣子的。

  1. 在K索引樹上找到K=3的記錄,取得ID=300.
  2. 再到ID索引樹查到ID=300對應的記錄。(第一次回表)
  3. 在K索引樹上找到K=5的記錄,取得ID=500.
  4. 再到ID索引樹查到ID=500對應的記錄。(第二次回表)
  5. 在K索引樹取下一個值K=6,不符合條件,查詢結束。

所以上面這條語句查詢了3條記錄K=3,5,6.回表了兩次。

  我們註意到一個細節,select * from T where k between 3 and 5這條語句查詢的結果是*,也就是所有的欄位的內容都會返回。而如果只使用K上的索引,則只能查詢到ID的值與K的值,並不能返回符合要求的所有欄位的值。那麼如果K上的索引查詢的結果可以滿足要求,是不是就不需要回表了呢?答案是肯定的。 如語句 SELECT ID from T where k between 3 and 5; ID的值已經在K索引樹上了,不需要回表就能返回結果。即索引“K”已經覆蓋了我們的查詢需求,我們稱為覆蓋索引。

  由於覆蓋索引可以減少樹的搜索次數,顯著提升查詢性能,所以使用覆蓋索引是一個常用的性能優化手段。

  上面的例子中還有一個小細節需要註意一下在引擎內部使用索引K其實讀了三個記錄,但對於MySQL的Server層來說,它就是找引擎拿到了兩條記錄。

最左首碼原則:

  InnoDB使用B+樹這種索引模型,由於B+樹的索引結構,可以利用索引的"最左首碼"來定位記錄。如你在‘name’欄位上建立了索引,當你的語句是 where name like ‘張%’時是可以使用索引的。MySQL會利用這個索引向後遍歷,直到不滿足條件為止。不止是索引的全部定義,只要滿足最左首碼,就可以利用索引來加速檢索。這個最左首碼可以是聯合索引的最左N個欄位,也可以是字元串索引的最左N個字元。索引建立聯合索引的時候,如何安排索引內欄位的順序就很重要了。 有一個原則是,如果通過調整順序,可以少維護一個索引,那麼這個順序就往往是應該優先採用的。

  如果既有聯合查詢,又有基於a,b各自的查詢呢?如果你建立的聯合索引是(a,b),那麼在這種情況下,只使用b來查詢是沒辦法使用索引的。這種時候我們需要優先考慮的就是空間了。如(name,age),name欄位一般來說會比age欄位占用更多的空間,那麼我們建立一個(name,age)的索引再加上一個(age)的索引就好了。

索引下推:

  還是上面的(name,age)索引為例,如果你查詢的條件是 姓張,且年齡小於30歲的所有男生,那麼你的查詢語句應該這麼寫。 select * from T where name like '張%'  and age = 10 and ismale = true; 由於索引首碼的規則,只能使用‘張’來找到滿足條件的記錄,然後再判斷查詢的其他條件是否滿足。在MySQL5.6之前,每條滿足條件 like '張%'的記錄都會回表進行判斷。MySQL5.6之後引入了索引下推(index condition pushdown),可以在索引遍歷的過程中對索引中包含的欄位先做判斷,直接過濾掉不滿足條件的記錄,減少回表的次數。舉個例子來說明 對於記錄 A(張一,40,男),B(張二,25,男),C(張三,26,女)。沒有索引下推時,A,B,C都需要進行回表判斷。有索引下推以後,A記錄中的age值為40,age欄位在查詢條件中,也在索引(name,age)中,觸發了索引下推,不進行回表。B,C仍需要回表。

上篇問題答案:

  對於普通索引k,重建時可以這麼寫:

  alter table T drop index k; alter table T add Index(k);

  對於主鍵索引,可以這麼寫:

  alter table T drop primary key; alter table T add primary key(id);

  對於上面的重建索引的作法,說出你的理解。如果有不合時的,為什麼?更好的作法是什麼?

  首先來回答一下為什麼要重建索引? 索引可能因為記錄的刪除,或者頁分裂等原因,導致數據頁有空洞,重建索引的過程會創建一個新的索引,把數據按順序插入,這樣頁面的利用率最高,也就是索引更緊湊,更省空間。

  重建索引K的做法是合理的。但重建主鍵過程不合理。不論是刪除主鍵還是創建主鍵,都會將整個表進行重建,所以連續執行這兩條語句,相當於第一個語句白做了。這兩條語句可以使用 alter table T engine =InnoDB來代替。

問題:

  表結構如下所示:

CREATE TABLE `geek` (
  `a` int(11) NOT NULL,
  `b` int(11) NOT NULL,
  `c` int(11) NOT NULL,
  `d` int(11) NOT NULL,
  PRIMARY KEY (`a`,`b`),
  KEY `c` (`c`),
  KEY `ca` (`c`,`a`),
  KEY `cb` (`c`,`b`)
) ENGINE=InnoDB;

  由於歷史原因, a和b需要做聯合主鍵。那麼既然主鍵包括了a,b這兩個欄位,又單獨在c上創建了一個索引,索引就已經包含了三個欄位了,為什麼還要創建ca,cb索引呢?有人給出的理由是業務里有這樣兩個查詢:

select * from geek where c=N order by a limit 1;
select * from geek where c=N order by b limit 1;

  這個理由對嗎?為了這兩個查詢,這兩個索引是否都必須呢?為什麼呢?


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一 Ceph文件系統 1.1 概述 Ceph 對象網關是一個構建在 librados 之上的對象存儲介面,它為應用程式訪問Ceph 存儲集群提供了一個 RESTful 風格的網關 。 Ceph 對象存儲支持 2 種介面: 相容S3: 提供了對象存儲介面,相容亞馬遜S3 RESTful介面的一個大子集 ...
  • 1.打開cmd命令行,查看當前配置 輸入 npm config ls 先看一下當前npm的配置環境,由於我已經修改過,所以可以看到修改後的路徑 2.修改路徑 這裡需要修改兩個路徑,module路徑和cache路徑 module對應prefix cache對應cache 首先在別的盤新建兩個目錄 D: ...
  • 進入系統安裝的第一個界面,開始系統的安裝操作。每一步的操作,左下角都會提示操作方式!! 1.選擇系統語言-English 2.選擇操作-Install Ubuntu Server 3.選擇安裝過程和系統的預設語言-English 4.選擇區域-other 5.選擇亞洲-Asia 6.選擇國家-Chi ...
  • 1、ubuntu網卡配置 1、查看網卡名稱 2、進行編輯網卡配置文件 更改網卡配置文件添加內容修改內容如下:下麵的enp0s3需要改成自己的網卡名稱。ip地址,掩碼網關自己合理配置就行了。記得wq!保存退出。 3、重啟網卡 4、ping百度測試 2、ubuntu安裝ssh服務 1、查看是否開啟ssh ...
  • 在實際的資料庫Sqlserver的運維的過程中,很多時候我們需要做到數據的備份操作,可以做到定時備份,也可以進行手動資料庫備份。在實際的過程中,有時候因業務需要備份出完整資料庫,而有時候又因為實際業務只需要影響到一張表或者幾張表,備份整個資料庫未必是最優的方案,此時可採用生成腳本或者Select I ...
  • 一、介面回調+自定義分區 1.介面回調:在使用消費者的send方法時添加Callback回調 註意:在自定義分區後,你的消費者會收不到消息,因為消費者預設接收的分區為0。 二、攔截器 1)創建生產者類; 2)創建自定義攔截器類實現ProducerInterceptor介面,重寫抽象方法; 3)在業務 ...
  • 在一次考試中,筆者因考試的電腦上沒有安裝操作Mysql資料庫的可視化工具而不知如何操作資料庫,所以在這裡可以提醒各位掌握 命令行來操作資料庫也是非常重要的。 筆者以慘痛的教訓來警惕大家。 進入正題: 使用命令行來操作資料庫分為以下幾個步驟: 前提: windows +R 運行 cmd.exe 步驟一 ...
  • 一、Kafka概述 1.Kafka是一個分散式流媒體平臺,它有三個關鍵功能: (1)發佈和訂閱記錄流,類似於消息隊列或企業消息傳遞系統; (2)以容錯的持久方式存儲記錄流; (3)記錄發送時處理流。 2.Kafka通常應用的兩大類應用 (1)構建在系統或應用程式之間的可靠獲取數據的實時流數據管道; ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...