程序員看了都要收藏系列:Mysql進階知識乾貨筆記!

1、SQL執行順序以及常見SQL的join查詢

sql執行順序

手寫mysql

SELECT DISTINCT
         <select_list>
FROM
          <left table> <join type>
JOIN <right_table> ON <join_codition>
WHERE
          <where_condition>
HAVING
          <having_condition>
ORDER BY
          <  order_by_condition>
LIMIT       < limit number>

機讀順序程序員

1 FROM <left_table>

2 ON <join_condition>

3 <join_type> JOIN <right_table>

4 WHERE <where_condition>

5 GROUP BY <group by_list>

6 HAVING <having_condition>

7 SELECT

8 DISTINCT <select_list>

9 ORDER BY <order_by_condition>

10 LIMIT <limit_number>
  • sql機器執行順序

程序員看了都要收藏系列:Mysql進階知識乾貨筆記!

  • 七種join關係

程序員看了都要收藏系列:Mysql進階知識乾貨筆記!

2、索引

一、什麼是索引

索引是幫助MYSQL高效獲取數據的數據結構-->排好序的快速查找數據結構算法

咱們平時所說的索引,沒有特別指明,都是指B樹(多路搜索樹,不必定是二叉)
結構組織的索引。其中彙集索引,次要索引,覆蓋索引,複合索引,前綴索引,惟一索引默認都是使用B+樹索引,統稱索引,除了B+樹這種類型的索引外,還有哈希索引等。sql

二、優點

相似大學圖書館書目索引,提升數據檢索效率,下降數據庫的io成本
經過索引列對數據進行排序,下降數據排序的成本,下降了CPU的消耗數據庫

三、劣勢

實際上索引也是一張表,該表保存了主鍵與索引字段,並指向實體表的記錄,因此索引列也是要佔用空間的緩存

雖然索引大大提升了查詢速度,同時卻會下降更新表的速度,如對錶進行INSERTE,UPDATE,和DELETE。由於更新表時,MYSQL不只要保存數據,還要保存一下索引文件每次更新添加了索引列的字段,都會調整由於更新所帶來的鍵值變化後的索引信息。(維護B+樹索引結構)服務器

索引只是提升效率的一個因素,若是你的MYSQL有大數據量的表,就須要花時間研究創建最優秀的索引,或優化查詢語句數據結構

四、索引分類

單值索引:即一個索引只包含單個列,一個表能夠有多個單列索引
惟一索引:索引列的值必須惟一,但容許有空值
複合索引:即一個索引包含多個列併發

五、基本語法

建立:
CREATE [UNIQUE] INDEX indexName ON myTable(clumn name(length));ide

使用ALTER命令建立:
一、添加主鍵(意味着索引值必須惟一,且不能爲NULL)
ALTER TABLE mytable ADD PRIMARY KEY(column_list)
二、建立惟一索引(索引值惟一,能夠爲NULL,爲NULL可重複出現)
ALTER TABLE mytable ADD UNIQUE index_name (column_list)
三、添加普通索引(索引值能夠出現屢次)
ALTER TABLE mytable ADD INDEX index_name(column_list)
四、指定索引爲FULLTEXT,用於全文索引
ALTER TABLE mytable ADD FULL TEXT index_name(column_list)

刪除:
DROP INDEX [indexName] ON mytable;
查看:
SHOW INDEX FROM table_name

六、索引結構原理

BTREE索引:

程序員看了都要收藏系列:Mysql進階知識乾貨筆記!

淺藍色的塊--->磁盤塊
黃色的塊------>指針
深藍色的塊----->數據項
P1表示小於17的磁盤塊,P2表示在17和35之間的磁盤塊,P3表示大於35的磁盤塊
真實的數據庫都存在與葉子節點,非葉子節點不存儲真實的數據,只存儲指引搜索方向的數據項

查找過程:
若是要查找數據項29,那麼首先會把磁盤塊1由磁盤加載到內存,此時發生一個IO,在內存中用二分繼續查找肯定19在17和35之間,鎖定磁盤塊1的P2指針,內存實踐相比磁盤IO可忽略不計。經過磁盤塊1的P2指針的磁盤地址把磁盤塊3由磁盤加載到內存,發生第二次IO,二分肯定29在26和30之間,鎖定磁盤塊3的P2指針,經過指針加載磁盤塊8到內存,發生第三次IO,同時在內存中二分查找到29,結束,總計三次io
二、HASH索引
三、full-text全文索引
四、R-TREE索引

哪些狀況須要建立索引?
一、主鍵自動創建惟一索引
二、頻繁做爲查詢條件的字段應該建立索引
三、查詢中與其餘表關聯的字段,外鍵關係創建索引
四、頻繁更新的字段不適合建立索引(由於每次更新都要維護索引結構)
五、where條件裏用不到的字段不建立索引
六、在高併發下傾向建立組合索引
七、查詢中排序的字段,排序字段若經過索引去訪問將大大提升排序速度
八、查詢中統計或者分組字段

哪些狀況下不適合建立索引
一、表記錄太少
二、常常增刪改的表
三、數據重複且分佈平均的表字段,所以應該只爲最常常查詢和最常常排序的數據列創建索引。(若是某個數據列包含許多重複的內容,爲它創建索引就沒有太大的實際效果)

3、 sql性能分析

一、Sql性能降低緣由

一、查詢語句寫的太爛
二、索引失效
三、關聯查詢包含太多的join
四、服務器調優及各個參數的設置(緩衝、線程數等)

二、explain關鍵字

定義

使用EXPLAIN關鍵字能夠模擬優化器執行SQL查詢語句,從而知道MYSQL是如何處理你的SQL語句的。分析你的查詢語句或是表結構的性能瓶頸

做用

一、可以獲取表的讀取順序
二、可以獲取數據讀取操做的操做類型
三、可以獲取哪些索引可使用
四、可以獲取哪些索引被實際是使用
五、可以獲取表之間的引用
六、可以獲取每張表有多少行被優化器查詢

命令

explain sql語句;

使用explain所獲取到的執行計劃包含的信息:

程序員看了都要收藏系列:Mysql進階知識乾貨筆記!

執行計劃信息各字段解釋

id
含義:select查詢的序列號,包含一組數字,表示查詢中執行select子句或操做表的順序
做用:解釋表的讀取順序
三種狀況:
一、id相同,執行順序由上至下
二、id不一樣,若是是子查詢,id序號會遞增,id值越大優先級越高,越先被執行
三、id有相同有不一樣,優先級越大的越先執行,相同的自上而下執行

select_type
含義:查詢的類型,主要用於區別普通查詢、聯合查詢、子查詢等複雜查詢
做用:解釋數據讀取操做的操做類型
類型:

  1. SIMPLE:簡單的select查詢,查詢中不包含子查詢或者UNION
  2. PRIMARY:查詢中包含任何複雜的子部分,最外層查詢被標記爲PEIMARY(即最後加載執行的表)
  3. SUBQUERY:在SELECT或WHERE列表中包含的子查詢
  4. DERIVED:在FROM列表中包含的子查詢被標記爲DERIVED(衍生) MYSQL會遞歸執行這些子查詢,把結果放在臨時表中
  5. UNION:若第二個SELECT出如今UNION以後,則被標記爲UNION;若UNION包含在FROM子句的子查詢中,外層SELECT將被標記爲DERIVED
  6. UNION RESULT:從UNION表獲取結果的SELECT

table
做用:標註數據來源哪張表

type
做用:顯示查詢使用了何種類型
類型性能排序:system > const > eq_ref >ref >range >index > ALL
通常狀況保證查詢至少達到range級別
類型解讀:
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
FULL TABLE SCAN 將遍歷全表找到匹配得行

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

key
做用 :代表實際查詢中用到得索引
狀況:
NULL:沒有使用索引(要麼沒建索引,要麼沒用索引,要麼用了索引失效)
注意:若是使用了覆蓋索引:則possible_keys爲null,而key有值

覆蓋索引:即查詢得字段得順序與個數與創建得複合索引一致

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操做中使用了覆蓋索引,避免訪問了表得數據行,效率不錯。若是同時出現using where表命索引被用來執行索引鍵值得查找;若是沒有出現using where 表命索引用來讀取數據而非執行查找動做。(好現象

  4. Using where:代表使用了where過濾
  5. using join buffer:代表使用了鏈接緩存
  6. impossible where : where子句得值總爲false,不能獲取到任何元組
  7. select tables optimized away
  8. distinct:優化distinct操做,在找到第一匹配得元組後即中止找一樣得動做

join語句優化總結

  1. 儘量減小join語句中得NestedLoop得循環總次數:「永遠用小結果驅動大的數據集」
    優先優化NestedLoop得內層循環

  2. 保證join語句中被驅動表上join條件字段已經被索引

  3. 當沒法保證被驅動表得join條件字段被索引且內存資源充足得前提下,不要吝嗇joinBuffer得設置

兩表關聯查詢:

左鏈接,索引建在右表;右鏈接,索引建在左表
三表關聯查詢:
左鏈接,索引建在右邊兩張表;右鏈接,索引建在左邊兩張表

4、 索引優化(解決or避免索引失效)

1.最佳左前綴法則:若是索引了多列(複合索引),要遵照最左前綴法則。指的是查詢從複合索引的最左列開始而且不跳過複合索引中得列(防止索引失效)

2.不要再索引列上作任何操做(計算、函數、(自動or手動)類型轉型),會致使索引失效而轉向全表掃描

3.存儲引擎不能使用索引中範圍條件右邊的列。即複合索引中若複合索引中某個列參與了範圍條件則該列後的全部列都會索引失效

例:複合索引--->(column1,column2,column3),如有條件查詢 where cloumn1 = value1 and cloumn2>1 and column3=values3 則column3將失效

4.儘可能使用覆蓋索引(只訪問索引的查詢(索引列和查詢列一致)),避免select *

5..mysql在使用不等於(!= 或者<>)的時候會致使索引失效而全表掃描

6.is null 或者 is not null 都會致使索引失效

7.like以通配符開始('%abc%')MySQL索引會失效而致使全表掃描。可是通配符只在右邊出現不會致使索引失效(即通配符不能夠出如今最左邊)

解決like '%字符串.....'索引失效問題:使用覆蓋索引,或者查詢複合索引中部分列

8.字符串不加單引號會致使索引失效

9.少用or,用它鏈接時會致使索引失效

5、查詢截取分析

查詢優化

1.切記小表驅動大表

  • in 和 exist用法場景區分:

select * from A where A.id in (select id from B)
當B表數據集小於A表數據集時,用in 優與exist

select * from A where exist (select 1 from B where B.id = A.id)
當A表數據集小於B表數據集時,用exist優與in

2.order by 關鍵字優化
mysql排序使用index和filesort兩種方式。儘可能使用using Index,避免出現using filesort

order by在知足下列條件會使用index方式排序:

  • order by 語句使用索引最左前列
  • 使用Where子句和order by子句條件列組合知足索引最左前列

若是order by字段不在索引列上,filesort有兩種算法:
雙路排序:mysql4.1以前的算法
單路排序:mysql4.1以後出現。從磁盤讀取查詢須要的全部列,按照order by 列在buffer對它們進行排序,而後掃描排序後的列表進行輸出。

程序員看了都要收藏系列:Mysql進階知識乾貨筆記!

3.group by 關鍵字優化
group by 實質是先排序後進行分組,遵守索引鍵的最佳左前綴,where高於having能寫在where限定的條件就不要使用having了

6、 慢查詢日誌

含義

MySQL的慢查詢日誌是MySQL提供的一種日誌記錄,它用來記錄在MySQL中相應實踐超過閾值的語句,具體指運行時間超過long_query_time值得SQL,則會被記錄到慢查詢日誌中

具體指運行時間超過long_query_time值的SQL,則會被記錄到慢查詢日誌中。long_query_time的默認值爲10s
經過自定義long_query_time收集追星shi的sql語句,結合explain進行分析調優

默認狀況下,MySQL數據庫沒有開啓慢查詢日誌。若是不須要調優,不建議啓動慢查詢日誌。

使用

查看是否開啓以及日誌路勁:SHOW VARIABLES LIKE '%slow_query_log%';

開啓:set global slow_query_log =1;

查看long_query_time:SHOW VARIABLES LIKE 'long_query_time%';

更改long_query_time: SET global long_query_time = 閾值 ;單位 秒
注意:這裏設置後不會立馬看出變化,從新鏈接就能夠看到最新設置
查詢當前系統有多少條慢查詢記錄:SHOW global status like '%Slow_queries%';

以上配置在數據庫重啓將會失效,若要永久有效則在[mysqlId]下配置

slow_query_log = 1;
slow_query_log_file = log file path
long_query_time=3;
log_output=FILE

日誌分析工具:mysqldumpslow
使用參數(可經過mysqldumpslow --help查看)
s:表示按照何種方式排序
c:訪問次數
l:鎖定時間
r:返回記錄
t:查詢時間
al:平均鎖定時間
ar:平均返回記錄數
at:平均查詢時間
t:返回前面多少條數據
g: 正則匹配
經常使用參考:
1.獲得返回記錄集最多的10個sql
mysqldumpslow -s r -t 10 日誌文件路徑
2.獲得訪問次數最多的10個sql
mysqldumpslow -s c -t 10 日誌文件路徑
3 獲得按照時間排序的前10條含有左鏈接的查詢sql
mysqldumpslow -s t -t 10 -g "left join" 日誌文件路徑

因爲可能數據過多,建議使用以上命令與more和管道|結合使用

7、 Show Profile

是什麼

是MySQL提供能夠用來分析當前會話中語句執行的資源消耗狀況,可用於SQL的調優的測量。

默認狀況下,參數處於關閉狀態,並保存最近15次的運行結果。

分析步驟

1.查看當前MySQL版本是否支持:SHOW variables like 'profiling' 默認爲關閉
2.開啓功能:set profiling = on;
3.運行SQL
4.查看結果:show profiles

程序員看了都要收藏系列:Mysql進階知識乾貨筆記!

5.診斷SQL:show profile cpu,block io for query 語句query_ID
可選參數:
ALL 顯示全部開銷信息
BLOCK IO 顯示塊IO相關開銷
CONTEXT SWITHES 上下文切換相關開銷
CPU 顯示CPU相關開銷信息
IPU 顯示發送和接收相關開銷
MEMORY 顯示內存相關開銷信息
PAGE FAULTS 顯示頁面錯誤相關開銷信息
SOURCE 顯示和Source_function,Source_file ,Source_line相關開銷
SWAPS 顯示交換次數相關開銷信息

常出現的危險status:
converting HEAP to MyISAM ----- 查詢結果太大,內存不夠用了往磁盤上加
Creating tmp table ---- 建立臨時表
Coping to tmp table on disk ---- 把內存中臨時表複製到磁盤
locked

8、 Mysql鎖機制

定義

鎖是計算機協調多個進程或線程併發訪問某一資源的機制

在數據庫中,除傳統的計算資源(CPU,RAM,I/O等)的爭用之外,數據也是一種供許多用戶共享的資源。如何保證數據兵法訪問的一致性、有效性是全部數據庫必須解決的一個問題,鎖衝突也是影響數據庫兵法訪問性能的一個重要因素。從這個角度來講,鎖對數據庫而言顯得尤爲重要也更加複雜。

鎖的分類

  • 從對數據操做的類型上分爲讀鎖和寫鎖
    讀鎖(共享鎖):針對同一份數據,多個讀操做能夠同時進行而不會互相影響
    寫鎖(排他鎖):當前寫操做沒有完成前,它會阻斷其餘寫鎖和讀鎖。

  • 從對數據操做的粒度分爲表鎖和行鎖

一、表鎖

特色:偏向MyISAM存儲引擎,開銷小,加速塊;無死鎖;鎖定粒度大,發生鎖衝突的機率最高,併發度最低。

命令:
加鎖: lock table 表名1 read/write,表名2 read/write......
查看錶加鎖狀況:show open tables;有鎖時In_user = 1
釋放表鎖:unlock tables

讀鎖:表被某一會話加上讀鎖後,你們均可以讀數據,可是不能夠寫(包括加鎖者,且加鎖者會話不能夠再操做其餘表),其餘會話發起寫數據請求將被阻塞到表鎖被釋放。

寫鎖:表被某一會話加上寫鎖後,加鎖者會話能夠對此表進行讀操做,但不能夠再操做其餘表。而其餘會話 對此表進行寫操做,讀操做將被阻塞至寫鎖被釋放。

總結:讀鎖會阻塞寫,可是不會阻塞讀;而寫鎖 會阻塞讀和寫

二、行鎖

特色:偏向InnoDB存儲引擎,開銷大,加鎖慢;會出現思索;鎖定力度最小,發生鎖衝突的機率最低,併發度也最高

注意:當索引失效或者無索引時時會致使行鎖變爲表鎖

三、間隙鎖

定義
當咱們用範圍條件而不是相等條件檢索數據,並請求共享或排他鎖時,InnoDB會給符合條件的已有數據記錄的索引項加鎖;對於鍵值在條件範圍內但不存在的記錄,叫作:「間隙(GAP)」

InnoDB也會對這個間隙鎖加鎖

危害:
由於Query執行過程當中經過範圍查找的話,他會鎖定整個範圍內全部的索引鍵值,即便這個鍵值不存在。
間隙鎖有一個比較致命的弱點,就是當鎖定一個範圍鍵值以後,及時某些不存在鍵也會被無辜鎖定,而形成在鎖定的時候沒法插入鎖定鍵值範圍內的任何數據。在某些場景下這可能會對性能形成很大的危害

優化建議

1.儘量讓全部數據檢索都經過索引來完成,避免無索引行鎖升級爲表鎖
2.合理設計索引,儘可能縮小鎖的範圍
3.儘量減小檢索條件,避免間隙鎖
4.儘可能控制事物大小,減小鎖定資源量和時間長度
5.儘量低級別事物隔離


寫在最後:

歡迎你們關注我新開通的公衆號【風平浪靜如碼】,海量Java相關文章,學習資料都會在裏面更新,整理的資料也會放在裏面。

以爲寫的還不錯的就點個贊,加個關注唄!點關注,不迷路,持續更新!!!

程序員看了都要收藏系列:Mysql進階知識乾貨筆記!

相關文章
相關標籤/搜索