目錄
(一)索引
1.索引的相關概念
2.B-樹和B+樹
3.索引的優缺點
4.索引的相分類
5.索引的創建
6.索引的刪除和查看
(二)關於SQL的性能分析
一、MySQL的邏輯分層
MySQL是我們平常用的很多的一個數據庫,雖然我們每天都在用CRUD在和它打交道,但對於它內部的一些技術細節瞭解的並不深入。例如當我們發送一條查詢語句的時候,在MySQL的服務端到底經歷了什麼呢?
其實MySQL邏輯上一共分爲四層,分別是連接層、服務層、引擎層、存儲層。到我們發送一條查詢語句的時候,
1.MySQL的連接層會先爲我們與MySQL建立連接並拿到SQL語句(僅僅是拿到語句,不做具體處理)
2.連接層建立連接並拿到SQL語句後就會把SQL語句交給服務層,服務層拿到SQL語句後會找服務層中對應的接口,服務層除了提供對應的增刪改查接口外還有另一個重要的功能就是提供SQL優化器,服務層拿到你發送過來的SQL語句後它會做一個判斷,如果它覺得你的這個SQL語句寫的不夠優雅,就會幫你優化然後在發送出去。
3.服務層拿到SQL並做了優化之後就會把優化後的SQL給到引擎層,引擎層會選擇把SQL給到當前數據庫所採用的某個存儲引擎。常見的存儲引擎有innoDB和MyISAM,innoDB是MySQL的默認存儲引擎。關於存儲引擎這一塊我們在下面具體介紹,這裏先大體有個概念。
4.存儲引擎在的到SQL後,最後會把最終的數據交給MySQL的最後一層——存儲層。我們最終的具體數據就是在存放在存儲層的。
二、數據引擎
我們剛剛在上面提到在MySQL的第三層“引擎層”中有兩個常見的存儲引擎(當然除了這兩個還有其他的不太常用),innoDB和myISAM。這兩者有什麼區別嗎?InnoDB是MySQL的默認存儲引擎,它在設計時遵循的是“事務優先”的理念,而MyISAM遵循的是“性能優先”的理念。比如說我們處理10萬條數據,那麼性能優先的MyISAM顯然速度會更快一些,但InnoDB會更安全一些。另外InnoDB使用的是“行鎖”,每次只鎖一行d的數據,而MyISAM是“表鎖”,一次鎖一整張表的數據,所以在效率和性能上InnoDB弱一些,但在安全性上InnoDB顯然更強。
InnoDB:事務優先(適合高併發場景)、行鎖
MyISAM:性能優先,表鎖
我們可以通過show engines;命令查看一下MySQL數據庫支持哪些引擎,如下,除了InnoDB和myISAM,MySQL還支持很多其他的存儲引擎:
既然MySQL支持這麼多存儲引擎,那我們能不能爲某張具體的表指定某個具體的存儲引擎呢?當然是可以的!現在我們就演示一下給弄張表指定具體的存儲引擎
1.先來創建一個數據庫並使用該數據庫 create myDB; use myDB;
2.在myDB中創建一張表,id爲主鍵,自增步長爲1(AUTO_INCREMENT=1),編碼爲utf-8(DEFAULT CHARSET=utf8),並指定這張表使用MyISAM存儲引擎(ENGINE=MyISAM)
create table tb(
id int(4) auto_increment,
name varchar(5),
dept varchar(5),
primary key(id)
)ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
三、SQL優化
上面講了MySQL的邏輯分層,存儲引擎,其實都是爲了做SQL優化做鋪墊,今天就簡單的對SQL優化做個簡要的概述。因爲一些諸如SQL性能低、執行時間長、SQL語句欠佳(主要針對多表的連接查詢)、索引失效、數據庫參數設置不好(如緩存區、線程數等)的原因,導致SQL效率很低,所以做SQL優化就是一件很有必要的事情,在數據量很大的時候,SQL優化就能很明顯的體現出其優勢。其實SQL的優化主要指的就是優化“索引(index)”,關於“索引”的具體內容我們下面分開來講解。
(一)索引
1.索引的相關概念:索引就相當於一本書的目錄,通過目錄我們一顆迅速定位書中要找的內容。MySQL中的索引也是一樣,它是一種幫助MySQL高效獲取數據的數據結構(樹)。這裏你有沒有想過爲什麼通過“樹”這種數據結構實現的索引就會提高SQL的效率呢?
這裏以查詢爲例,結合圖示簡單的做一下說明,假如我們有如下的一張表,在沒有引入索引之前假如我們想查詢表中的一條年齡爲20的數據,那麼就必須幾乎要遍歷完整個表才能查詢到這條數據;現在我們引入索引,並且以age列作爲索引列來構建出一個二叉樹的索引結構來,具體的構造過程是先把表中第一行的age(49)作爲二叉樹的頭結點,然後順序往下遍歷,把小於頭節點的age放到左邊,大於頭結點的age放到右邊,表中數據遍歷完以後就構造出了右圖所示的二叉樹索引結構。現在我們再來試着查找年齡爲20的數據所需要的過程:
1.將age爲20的數據先和頭結點的49比較(20<49),所以往左邊走
2.來到樹形結構的第二層,繼續和21比較(20<21),繼續往左邊走
3.來到樹形結構的第三層,和20比較(20=20),查找成功
所以你看,加上索引以後只需三次就查找成功了,可見索引確實可以提高我們SQL的查詢效率。
目前大部分數據庫系統及文件系統都採用B-Tree或其變種B+Tree作爲索引結構,它的具體實現就在我們上面提到的引擎層的存儲引擎中。像上面提到的MyISAM存儲引擎就使用B-Tree來實現主鍵索引、唯一索引和非主鍵索引等。而InnoDB中的非主鍵索引使用的是B-Tree數據結構,主鍵索引則使用的是B+Tree。那麼B-Tree和B+Tree到底有什麼區別呢?
2.B-Tree和B+Tree異同
B-Tree:它類似於像上面構建的那種普通二叉樹,但是B-樹允許每個節點有更多的子節點(二叉樹只允許有兩個),B-樹示意圖如下:
B-樹的特點:
(1)所有鍵值分佈在整個樹中(B+Tree只分布在葉子節點中)
(2)任何關鍵字出現且只出現在一個節點中
(3)搜索有可能在非葉子節點結束
(4)在關鍵字全集內做一次查找,性能逼近二分查找算法
B+Tree:B+樹是B-樹的變體,B+樹的示意圖爲:
從圖中也可以看到,B+樹與B-樹的不同在於:
(1)所有關鍵字存儲在葉子節點,非葉子節點不存儲真正的data
(2)爲所有葉子節點增加了一個鏈指針
3.索引的優缺點:
索引的弊端:1.索引本身是存儲在文件中,所以一般存放在硬盤中,導致其會暫用一定的空間。
2.以下情況不建議用索引:a.數據量小 b.頻繁更新的字段 c.很少使用的字段
3.索引會提高數據的“查詢”效率,但是會降低“增刪改”的效率
索引的優勢:1.提高查詢效率:本質是降低了I/O的使用率,因爲查詢會到磁盤去找數據,這就涉及到I/O操作
2.降低了CPU的使用率:當SQL語句中有..order by的時候 因爲B樹索引本身就是一個排好序的結構,因此在排序時可以直接使用,而不需要再查找出結果後勞煩CPU來通過比較再進行排序。
4.索引的分類:
單值索引:單列 。像上面列舉的age爲索引列, 一個表可以有多個單值索引
唯一索引:同單值索引唯一不同的地方就是唯一索引不可重複,比如將入上面表中的age列有相同年齡的兩個值,那麼age列 就不能作爲唯一索引
主鍵索引:同唯一索引相同,都不可重複,唯一不同點就是唯一索引可以有null值,主鍵索引不可以有null
複合索引:多個列構成的索引,如(name,age)兩個列組合成的索引。
5.索引的創建:
方式一:create 索引類型 索引名 on 表名(字段名);
單值索引:create index dept_index on tb(detp);
唯一索引:create unique index name_index on tb(name);
複合索引:create index dept_name_index on tb(dept,name);
方式二:alter table 表名 add 索引類型 索引名(字段名);
單值索引:alter table tb add index dept_index(dept);
唯一索引:alter table tb add unique index name_index(name);
複合索引:alter table tb add index dept_name_index(dept,name);
注意:如果一個字段是primary key,那麼該字段默認是主鍵索引。
5.索引的刪除和查詢:
刪除索引:drop index 索引名 on 表名;
drop index name_index on tb;
查詢索引:show index from 表名;
(二)關於SQL的性能分析
關於這一塊的內容,我們需要清楚兩個地方:
1.分析SQL的執行計劃:所謂“分析SQL的執行計劃”其實指的就是通過explain+SQL語句來查詢我們SQL語句的執行情況,因爲explian命令可以模擬服務層的SQL優化器執行SQL語句,從而讓我們開發人員知道自己編寫的SQL的狀況。
2.有時候MySQL服務層的SQL優化器會干擾我們的優化:有時候我們通過上面第一步的“分析SQL的執行計劃”瞭解到自己SQL存在的問題後,然後自己做了相應的優化,但是偶爾我們會發現在SQL執行時並沒有按我們優化過的SQL語句去執行。引起這個的主要原因就是我們在上邊提到的服務層的SQL優化器,雖然我們做了SQL優化,但有時候SQL優化器會認爲你優化的不夠好,它會自動爲你重新優化,而這樣做有時候就會導致最後執行的結果與我們到處想要的不一樣。
更多的優化方法可參考官方文檔:https://dev.mysql.com/doc/refman/5.5/en/optimization.html