【數據庫之美】SQL調優-索引機制

去年整理的筆記,拿出來整理到csdn上吧。在數據庫中,可以分成幾個模塊進行劃分 事務、索引、ACID特性、鎖。而本章主要針對索引和鎖展開介紹,索引的出現很大程度上提高了數據庫的併發能力。所以下面,我們開始吧。

1、mysql架構介紹

在這裏插入圖片描述

mysql特點:

和其他數據庫相比,Mysql有點與衆不同,他的架構可以在多種不同的場景中應用併發揮良好作用,主要體現在存儲引擎的架構上,
插件式的存儲引擎架構將查詢處理和其他的系統任務以及數據的存儲提取相分離。這種架構可以根據業務的需求和實際選擇適合的存儲引擎。

1.連接層

最上層是一些客戶端和連接服務,包含本地sock通信和大多數基於客戶端/服務端工具實現的類似於tcp/ip的通信,主要完成一些類似於連接
處理,授權認證,以及相關的安全方案。在改層上引入了線程池的概念,爲通過認證安全接入的客戶端提供線程,同樣在改層上可以實現基於
SSL的安全鏈接,服務器也會爲安全接入的每個客戶端驗證它所具有的操作權限。

2.服務層

第二層架構主要完成大多數的核心服務功能,如sql接口,並完成緩存的查詢,SQL的分析和優化及部分內置函數的執行,所有跨存儲引擎
的功能也在這一層實現,如過程,函數等。在該層,服務器會解析查詢並創建相應的內部解析樹,並對其完成相應的優化如確定查詢表的
順序,是否利用索引等,最後生成相應的執行操作,如果是select語句,服務器還會查詢內部的緩存,如果緩存空間足夠大,這樣在解決大量
讀操作的環境中能夠更好的提升系統的性能。

3.引擎層

存儲引擎層,存儲引擎真正的負責了mysql中數據的存儲和提取,服務器通過api與存儲引擎進行通信,不同的存儲引擎具有的功能不同
這樣我們可以根據自己的實際需要進行選取,後面介紹myiSAM和InnoDB

4.存儲層

數據存儲層,主要是將數據存儲在運行於裸設備的文件系統之上,並完成與存儲引擎的交互。

MyiSAM 和InnoDB區別

在這裏插入圖片描述

2、索引優化分析

2.1 索引簡介

sql性能慢原因

  • 索引失效
  • 關聯查詢太多join
  • sql執行順序

人寫

在這裏插入圖片描述

機讀

在這裏插入圖片描述

sql解析

在這裏插入圖片描述

七種join

內連接

在這裏插入圖片描述

1.內連接:select <select_list> from TableA A inner join TableB B on A.key = B.key

左連接

在這裏插入圖片描述

2.左連接:select <select_list> from TableA A Left join TableB B on A.key = B.key

右連接

在這裏插入圖片描述

3.右連接:select <select_list> from TableA A right join TableB B on A.key = B.key

在這裏插入圖片描述

select <select_list> from tableA A left join tableB B on A.key = B.key where B.key is null;

在這裏插入圖片描述

select <select_list> from tableA A right join tableB B on A.key = B.key where A.key is null;

全連接
在這裏插入圖片描述
select <select_list> from TableA A full outer join TableB B on A.key = B.key

在這裏插入圖片描述
select <select_list> from TableA A Full outer join tableB B On A.key = B.key where A.key is Null or B,key is null

索引簡介

索引:Mysql官方對索引的定義爲 索引(index)是幫助Mysql高效獲取數據的數據結構索引的本質就是數據結構
排好順序的快速查找數據結構。
結論:數據本身之外,數據庫還維護着一個滿足特定查找算法的數據結構,這些數據結構以某種方式指向數據,這樣可以在這些數據結構基礎之上實現高級查找算法,這種數據結構就是索引。
一般來說索引本身也很大,不可能全部存儲在內存中,因此索引往往以索引文件的形式存儲在磁盤上。
我們平時所說的索引,如果沒有特別指明,都是B樹索引(多路查找樹,並不一定是二叉樹)結構組織的索引,其中聚集索引次要索引,覆蓋索引,複合索引,前綴索引,唯一索引默認使用B+樹索引,統稱索引。當然,除了B+樹這種類型的索引之外,還有**哈希索引(hash Index)**等。
優勢:類似於圖書館建書目索引,提高數據檢索的效率,降低數據庫的IO成本
通過索引對數據庫進行排序,降低數據排序的成本,降低了CPU的消耗
劣勢:實際上索引也是一張表,該表保存了主鍵和索引字段,並指向實體表的記錄,所以索引列也是要佔用空間的
雖然索引大大提高了查詢速度,同時卻會降低更新表的速度。對錶進行insert delete update。在更新表的時候,mysql不僅要
保存數據,還要保存一下索引文件每次更新添加了索引列的字段。都會調整因更新所帶來的鍵值變換的索引信息。索引只是提高效率的一個因素,如果你的mysql有大量數據的表,需要花時間建立優秀的索引,或者優化查詢語句。

索引分類

1.單列索引 :一個索引只包含單個列,一個表可以有多個單列索引。
2.唯一索引 :索引列的值必須是唯一,但允許有空值
3.複合索引:一個索引包含多個列。

基本語法:

索引創建:

 	create [unique]INDEX indexName on tableName(columnname)  創建一個索引
    ALTER tableNAME ADD [unique] index [indexName] on (columnname) 給一張表添加索引
    刪除索引:drop index indeName on TableName;
	查看索引:show index from tableName;

mysql索引結構

檢索原理

在這裏插入圖片描述
在這裏插入圖片描述

那些情況下需要創建索引

1.主鍵自動增長建立唯一索引
2.頻繁作爲查詢條件的字段應該建立索引
3.查詢中與其他表關聯的字段,外鍵關係建立索引
4.頻繁更新的字段不適合創建索引(每次更新不單單更新數據 還更新索引,加重了IO負擔)
5,where條件裏用不到的字段不用創建索引。
6.單鍵/組合索引的選擇問題,who(在高併發下傾向於創建組合索引)
7.查詢中排序的字段,排序字段若通過索引去訪問將大大提高排序速度。
8.查詢中統計或者分組字段

那些情況下不需要創建索引

1.表記錄少
2.經常增刪改查的表(提高了查詢效率,同時會降低更新表的速度,如對錶進行insert update delete 因爲更新表,mysql不僅更新數據,同時還要更新索引文件)
3.數據重複且分佈平均的表字段,因此應該只爲最經常查詢和最經常排序的數據列建立索引,注意 如果某個數據列包含許多重複的內容,爲它創建索引就沒有太大實際效果。
在這裏插入圖片描述

2.2. 性能分析

1、Mysql Query Optimizer

在這裏插入圖片描述

2、mysql常見瓶頸

CPU:cpu在飽和的時候一般發生在數據轉入內存或從磁盤上讀取數據時候
io:硬盤i/o瓶頸發生在裝入數據遠大於內存容量的時候
服務器硬件的性能瓶頸:top free iostat vmstat來查看系統的性能狀態

3、explain

explain:使用關鍵字可以模擬優化器執行SQL查詢語句,從而知道mysql是如何處理你的sql語句,分析你的查詢語句或是表結構的性能瓶頸。
作用:
1、表的讀取順序
2、數據讀取操作的操作類型
3、那些索引可以使用
4、那些索引被實際使用
5、表之間的引用
6、每張表有多少行被優化器查詢
用法:explain+SQL語句
**執行計劃包含的信息 id select_type table type possiable _keys key key_len ref rows extra

各字段解釋

id

select查詢的序列號 包含一組數字 表示查詢中執行的select子句或操作表的順序。
三種情況

  • id相同 執行順序由上至下

  • 在這裏插入圖片描述

  • id不同 如果是子查詢 id的序號會遞增 id值越大優先級越高 越先被執行
    在這裏插入圖片描述
    先執行t3 在執行t1 在執行t2

  • id相同不同 同時存在

  • 在這裏插入圖片描述
    執行順序 2 1 1 也就是說先執行t3 t3執行完畢後在執行 t1 t2

select_type

在這裏插入圖片描述

查詢的類型(主要是用於區別 普通查詢、聯合查詢、子查詢等的複雜查詢)
SIMPLE - 簡單的select查詢,查詢中不包含子查詢或者union

explain select * from Student;

PRIMARY - 查詢中若包含任何複雜的子部分,最外層查詢則被標記爲

explain select * from Student where sno = 201215121;

SUBQUERY - 在select或where 列表中包含子查詢

explain select * from Student where sno = (select sno from Student where sname = '李勇');

DERIVED - 在from 列表中包含的子查詢被標記爲DERIVED(衍生)MYSQL會遞歸執行這些子查詢,把結果放到臨時表裏。
UNION - 若第二個select出現在UNION之後,則被標記爲UNION 若UNION包含在from子句的子查詢中,外層select將標記爲DERIVED
UNION RESULT - 從UNION表獲取結果的SELECT

table 顯示這一行的數據是關於那張表的

type
在這裏插入圖片描述

顯示查詢使用了何種類型 從最好的到最差的一次是System>const>eq_ref>ref>range>index>all

System -

表中只有一條記錄(等於系統表),這是const類型的特例,平時不會出現,這個也可以不用記憶

const-

在這裏插入圖片描述
表示通過索引一次 就可以找到了,const用於比較primary key或者unique索引,因爲只匹配一行數據,所以很快。如將主鍵置於where列表中,mysql就能將該查詢轉換成一個常量。

eq_ref:

在這裏插入圖片描述
唯一性索引掃描,對應每個索引鍵,表中只有一條記錄與之匹配,常見於主鍵或唯一索引掃描。

ref:

在這裏插入圖片描述
非唯一性索引掃描,返回匹配某個單獨值的所有行。本質上也是一種索引訪問,它返回所有匹配某個單獨值的行,然而。他可能會找到多個符合條件的行,所以他應該屬於查找和掃描的混合體。

range:

在這裏插入圖片描述
只檢索給定範圍的行,使用一個索引來選擇行,key列顯示使用了哪個索引,一般就是在你的where語句中出現between < > in等的查詢。這種範圍掃描索引掃描比全表掃描要好,因爲它只需要開始與索引的某一點,而結束另一點,不用掃描全部索引。

index :

在這裏插入圖片描述
full index scan index 與ALl 區別爲index類型只遍歷索引樹,這通常比ALL快因爲索引文件通常比數據文件小,(也就是說雖然all和index都是讀取全表,但是index是從索引中讀取的,而ALL是從硬盤中讀的)

all

在這裏插入圖片描述
:full table scan 將遍歷全表以找到匹配的行

一般來說,得保證查詢至少達到range級別,最好能達到ref
在這裏插入圖片描述

possible_key

顯示可能應用到這張表中的索引,一個或多個 查詢涉及到的字段上若存在索引,則該索引將被列出,但不一定被查詢實際使用

key

實際使用的索引。如果爲null 則沒有使用索引。
查詢中若使用了覆蓋索引,則該索引和查詢的select字段重疊。

key_len

表示索引中使用的字節數,可通過該列計算查詢中使用的索引的長度,在不損失精確性的情況下,長度越短越好
key_len 顯示的值爲索引字段可能的最大長度,並非實際使用長度。既key-len是根據表定義計算而得,不是通過表內檢索出的。

ref

在這裏插入圖片描述
顯示索引的那一列被使用了,如果可能的話,是一個常數,那些列或常量被用於查找索引列上的值

rows

根據表統計信息及索引選用情況,大致估算出找到所需的記錄所需要讀取的行數
在這裏插入圖片描述

extra

包含不適合在其他列中顯示但十分重要的額外信息

1.Using filesort

說明mysql會對數據使用一個外部的索引排序而不是按照表內的索引順序進行讀取,mysql中無法利用索引完成的排序操作稱爲“文件排序”

2.Using temporary

使用了臨時表保存中間結果mysql 在對查詢結果排序時使用臨時表,常見於排序order by 和分組查詢group by

3.Using index

表示相應的select操作中使用了覆蓋索引(Covering index),避免訪問了表的數據行,效率不錯。
如果同時出現using where表明索引被用來執行索引鍵值的查找,如果沒有同時使用using where 表明索引用來讀取數據而非執行查找動作。 覆蓋索引

4.Using where

表明使用了where過濾

5.using join buffer

使用了連接緩存

6.impossible where

where子句的值總是false 不能用來獲取任何元組

7.select tables optimized away

在沒有使用group by 子句的情況下,基於索引優化MAX/MIN操作或者 對於MyISAM存儲引擎優化COUNT(*)操作,不必等到執行階段在進行計算,查詢執行計劃生成的階段既完成優化。

8.distinct

優化distinct操作 在找到第一匹配的元組後既停止找同樣值的動作。

在這裏插入圖片描述在這裏插入圖片描述

2.3 索引優化

索引分析

單表

在這裏插入圖片描述

兩表

在這裏插入圖片描述

三表

在這裏插入圖片描述
索引失效

2.最佳左前綴法則

在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述

索引失效

全值匹配我最愛
最佳左前綴法則-如果索引了多個列,要遵守最前綴法則,指的是查詢從索引的最左前列開始並且不跳過索引中的樹。
不在索引列上做任何操作(計算、函數(自動or手動)類型轉換),會導致索引失效而轉向全表掃描
存儲引擎不能使用索引中範圍條件右邊的列
**儘量使用覆蓋索引(只訪問索引的查詢(索引列和查詢列一致)) 減少select ***
mysql在使用不等於(!= >= <= )的時候無法使用索引會導致全表掃描。
is null is not null 也無法使用索引
like 以通配符開頭(’%abc%’)mysql索引會失效變成全表掃描的操作,

解決like’%abc% 索引不失效 使用組合索引
字符串不加單引號索引會失效
少用or 用它來連接時會索引失效。'

在這裏插入圖片描述
在這裏插入圖片描述
一般性建議

3、查詢截取分析

4、mysql鎖機制

概述
定義:鎖是計算機協調多個進程或線程併發訪問某一資源的機制。
在數據庫中,除傳統的計算機資源(cpu io ram )的爭用以外。數據也是一種供許多用戶共享的資源,如何保證數據併發訪問的一致性,有效性是所有數據庫必須解決的一個問題。鎖衝突也是影響數據庫併發訪問性能的一個重要因素,從這個角度來說,鎖對數據庫而言顯得尤爲重要,也更加重要。
在這裏插入圖片描述

鎖分類

從數據操作的類型(讀/寫)分

讀鎖(共享鎖):針對同一份數據,多個讀操作可以同時進行而不會互相影響
寫鎖(排他鎖):當前寫操作沒有完成前,他會阻斷其他寫鎖和讀鎖。

從對數據操作的粒度分

表鎖
行鎖

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

三鎖

表鎖

特點:偏向於MyISAM存儲引擎,開銷小,加鎖快 無死鎖 鎖定粒度大,發生鎖衝突的概率最高,併發度最低

行鎖

特點
偏向於InnoDB存儲引擎,開銷大,加鎖慢 會出現死鎖 鎖粒度最小 發生鎖衝突的概率最低,併發度最高。
InnoDB和MyISAM的最大不同有兩點,一直支持事務Transaction 而是採用了行級鎖

事務

事務及其ACID屬性

併發事務帶來的問題

更新丟失
髒讀
不可重複讀
幻讀

事務隔離級別

優化建議
儘可能讓所有數據檢索都通過索引來完成,避免無索引行鎖升級爲表鎖
合理設計索引,儘量縮小鎖的範圍
儘可能控制事務大小,減少鎖定資源和時間和長度
儘可能低級別事務隔離

頁鎖

開銷和加鎖時間界於表鎖和行鎖之間,會出現死鎖,鎖定粒度介於表鎖和行鎖之間 併發度一般
5、主從複製

linux下mysql自啓動
linux > chkconfig mysql on;將mysql設置爲自啓動
linux > service mysql start;mysql啓動
linux > service mysql stop;mysql關閉
linux > ntsysv #查看是否自啓動
linux > ps -ef | grep mysql ;在linux下查看安裝目錄
mysql > show variables like '%char%';查看數據庫字符編碼

------
mysql> show engines;查看mysql提供什麼存儲引擎
mysql> show open tables;//展示那些表上鎖了。
mysql> unlock tables;釋放鎖
mysql> lock table 表名 read;讀鎖
mysql> lock table 表名 writer;寫鎖
mysql> set autocommit=0;設置不自動提交
mysql> commit ;提交
mysql> set autocommit=1;自動提交

1.使用explain 語句讓mysql解釋它將如何執行一條select語句
2.一般來說,存儲過程執行的一條條的的執行其中的各條mysql語句快。
3.應該總是使用正確的數據類型
4.絕對不要檢索比需求還多的數據,換言之,不要使用select
5.導入數據時,應該關閉自動提交,在導入完成之後在重建他們。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章