MySQL --- SQL解析 與 性能分析工具

  • 一. SQL解析及優化

1 . SQL解析

SQL進入引擎的流程

 

Eg:select XXX  from ….join …on …where  ….group by …having …order by …limit

解析順序:from …on..join … where …group by …having …select …order by .limit

1.1 sql在MySQL服務上的執行流程

參考:www.cnblogs.com/annsshadow/p/5037667.html

      dev.mysql.com/doc/refman/5.7/en/memory-use.html

2. 優化工具:

    1. Explain 執行計劃使用方法

2.1.1. explain 結果參數說明

Eg:優化前SQL:

explain select a.account_id ,a.user_id ,a.course_id

from  study_right_logger_11 a  join user b on a.user_id = b.user_id

 where   a.account_id = '60258144'  or a.course_id= '124162'  ;

備註:study_right_logger_11 建立符合索引順序:`account_id`, `course_id`, `user_id`

(1).

結果參數

參數類型

作用

含義

id

Id值相同:從上往下順序執行,數據少的表優先查詢

Sql中table的執行順序

表的執行順序因表的行數的變化而改變:笛卡爾積

Id值不同越大越優先查詢(有子查詢時)

 

 

Select_type

Primary:

包含子查詢SQL的主查詢,最外層

 

Subquery:

包含子查詢SQL的子查詢,非最外層

 

Simple

不包含:子查詢和union

 

Derived:衍生查詢

使用了臨時表

  1. 在from 子查詢中只有一張表
  2. 在from的子查詢中如果有talble1 union table2 ,則table1就是derived

 

Union:

衍生表,如下圖1

 

Table

Derived + id(衍生表)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Type

system

理想情況,實際達不到。只有一條數據的系統表或衍生表只有一條數據的主查詢.eg:select * from (

Select * from test1)t where tid =1; test1中只有一條數據

索引類型

const

僅能查到一條數據是SQL

用於primary key 或unique索引

結果僅有一條數據

eq_ref

唯一性索引,對於每個索引鍵的查詢,返回匹配唯一行數據,有且只有1個不能爲0( 如果表中的索引列有沒查詢出來的數據則認爲是0 ,即全部索引列必須全部查詢出來,基本很難滿足)。

即索引列的每個值都是唯一的,eg:name 全是唯一的,且是索引列

結果是多條數據,但每條數據唯一

ref

非唯一性索引,對於每個索引鍵的查詢返回匹配的所有行。

結果是多條,(0 或者多條)

range

查詢指定範圍的行,where後面是一個範圍查詢(between,< ,> ,in 有時會失效,轉爲無索引)

 

Index

查詢全部索引數據

 

 

all

查詢全部表中的數據,全表掃描

 

Index_merge

MySQL5.0之前,一個表一次只能使用一個索引,無法同時使用多個索引分別進行條件掃描。但是從5.1開始,引入了 index merge 優化技術,對同一個表可以使用多個索引分別進行條件掃描

 

index merge intersect

 

Possible_keys

具體索引列

 

表示可能用到的索引,是一種預測

 

Null

沒有使用索引

 

key

 

 

實際使用到的索引

 

 

 

 

Key_len

索引的長度

如果長度是0 ,則該索引列未被使用,用於判斷符合索引是否完全被使用

( a,b,c )三個列的符合索引

符合索引如果要使用後面的列的索引則必然前面是索引也要使用

Utf-8:1個字符佔用3個字節

A.如果列 是char(10 )則該列佔3 * 10

B.如果索引字段可以爲null,則會使用1個字節用於標識

C.如果類型是varchar 則除了有一位null的標識,還會用2個字節標識可變長度。即最後多出3位

C. int型佔用4個字節,索引中只包含了1列,所以,key_len是4

 

D .

ref

Const

 

當前表所參照的字段

 

 

 

 

 

 

rows

整數

 

通過索引查詢到的數據行數

 

 

 

extra

(一)

Using filesout

性能消耗很大,SQL需要優化

 

Eg:select * from table1 where a1 = XX order by a2 ; 即:using filesout.

A.對於單索引,如果排序和查詢的列是同一個字段則不會出現using filesout ;如果排序和查詢不是同一個字段,則需要額外查詢,則是using filesout

 

 

B.複合索引:不能跨列

Eg:( a1,a2,a3)複合索引列

Select * from table where a1=XX order by a3;

a1跟a3跨列了,

Select * from table where a2=XX order by a3;

a1被跨了,同樣是using filesout

 

Where 和orderby 按照複合索引的順序使用,不要跨列

 

(二)

Using temporary:同樣性能損耗很大,用到了臨時表,常出現在group by

Eg:select a1 from table where a1 in( 1,2,3 ) group by a2;

查詢的a1 但是根據a2分組,會導致MySQL再創建臨時表查詢結果

則extra 就是Using temporary,所以要查詢和排序列一致

注:解析過程

From..on..join..where..group by..having..select distinct ..orderby limit…

Eg:select * from table where a2=2 and a4=4 group by a2,a4 ;--沒有using temporary

 

Select * from table where a2 =2 and a4=4 group by a3;using temporary

 

 

 

(三)

Using index 性能提升的標識—索引覆蓋

說明當前的SQL不讀取原文件,只從索引文件獲取數據,不需要回表查詢

只要查詢的列全部都在索引中就會是using index

Eg:複合索引( a1, a2,a3 )

Select a1,a2 from table where a1 =XX and a2=XXX

上面的SQL就會使用using index

 

 

 

 

 

 

 

 

(四)

Using where :需要回表查詢

Eg:a1 是索引列

Select a1,a2 from table where a1=XX

上面是SQL必須回原表查詢a2

 

也有特殊情況,MySQL底層的優化器也會幫助優化SQL語句

Eg:複合索引:a1,a2,a3

Select a1,a2,a3 from table where a2=X and a1=x and a3=xx;

上面雖然跟複合索引順序不一致,但也是using index 是因爲SQL優化器的結果

 

Eg:複合索引:a1,a2,a3

Select a1,a2,a3 from table where a1=1 and a3=3 order by a2;

結果是:Using index + Using where

A1在索引中可以直接查詢,但a3無效因爲跨列了,則需要回表查詢(using where )

 

 

 

五.

using index condition:查找使用了索引,但是需要回表查詢數據

 

 

 

六.

using intersect:表示使用and的各個索引的條件時,該信息表示是從處理結果獲取交集

using union:表示使用or連接各個使用索引的條件時,該信息表示從處理結果獲取並集

using sort_union和using sort_intersection:與前面兩個對應的類似,只是他們是出現在用and和or查詢信息量大時,先查詢主鍵,然後進行排序合併後,才能讀取記錄並返回。

 

七.using join buffer

mysql 引擎使用了連接緩存,說明SQL質量很差

 

 

 

 

 

2.2  profile

mysql5.0.3版本以後纔開放的。但是在mysql5.7之後,profile信息將逐漸被廢棄,mysql推薦使用performance schema

2.2.1. 開啓使用

可以定位SQL執行過程中對CPU和io的消耗

(1)方法一

     

   A.查看是否啓用:SELECT @@profiling;

                開啓profile :SET profiling = 1; //臨時打開,而不是全局打開

      當打開後,所有的SQL語句全部記錄

   B. 查看記錄 :query :show profile for query 1; // 數字表示查詢的ID

      備註:在使用profile查看執行過程記錄之前要先把profile關閉掉,即:

                  SET profiling = 0;

   C. show profile cpu,block io,memory,swaps for query 查詢ID;

   D.用show profiles;可以查詢之前操作SQL對應的ID值

缺點:消耗性能,在生產環境是關閉的

(2)方法二:查詢全局日誌,記錄了開啓後的全部SQL日誌

     查看命令:show variables like '%general_log%';

     打開全局日誌命令:set global general_log=1; 或等2

      文件會記錄:mysql.general_log  ( mysql 庫的general_log 表 )

2.2.2 查詢參數

備註:使用select @@ mysql的配置參數名稱,就可以查詢出該參數對應的具體值

Eg:

如果IO的in和out 都是0 說明數據都已經被緩存在內存中了。

2.3.performance_schema 系統級存儲引擎

2.3.1. 介紹

A.MySQL的performance schema 用於監控MySQL運行過程中的資源消耗、資源等待等情況。主要關注數據庫運行過程中的性能相關的數據,與information_schema不同,information_schema主要關注server運行過程中的元數據信息

B.提供了一種在數據庫運行時實時檢查server的內部執行情況的方法。performance_schema 數據庫中的表使用performance_schema存儲引擎。該數據庫主要關注數據庫運行過程中的性能相關的數據

C.server內部活動中所做的任何事情以及對應的時間消耗

Dperformance_schema中的事件只記錄在本地serverperformance_schema中,其下的 這些表中數據發生變化時不會被寫入binlog中,也不會通過複製機制被複制到其他server

Eperformance_schema的表中的數據不會持久化存儲在磁盤中,而是保存在內存中,一旦服務器重啓,這些數據會丟失

 

2.3.2. 使用介紹

2.3.2.1.查詢當前MySQL的實例是否支持,

命令:show engines;

2.3.2.2.performance_schema被視爲存儲引擎

查看是否支持命令:

SELECT * FROM INFORMATION_SCHEMA.ENGINES WHERE ENGINE ='PERFORMANCE_SCHEMA';

2.3.2.3.啓用方法

   performance_schema5.7.x及其以上版本中默認啓用(5.6.x及其以下版本默認關閉),如果要顯式啓用或關閉時,我們需要使用參數performance_schema=ON|OFF設置,並在my.cnf中進行配置

   [mysqld]

performance_schema = ON  # 注意:該參數爲只讀參數,需要在實例啓動之前設置才生效

2.3.2.4.查詢是否開啓,

命令:SHOW VARIABLES LIKE 'performance_schema';

2.3.2.5.查詢引擎涉及到的所有表:

   performance_schema引擎相關的元數據來了解在performance_schema下存在着哪些表:

   命令:SELECT * FROM INFORMATION_SCHEMA.TABLES

WHERE TABLE_SCHEMA ='performance_schema' and engine='performance_schema';

2.3.3. performance_schema表的分類

performance_schema庫下的表可以按照監視不同的緯度進行了分組,例如:或按照不同數據庫對象進行分組,或按照不同的事件類型進行分組,或在按照事件類型分組之後,再進一步按照帳號、主機、程序、線程、用戶等

2.3.3.1. 事務相關

事務事件記錄表,記錄事務相關的事件的表,與語句事件類型的相關記錄表類似:

A.查詢語句:show tables like 'events_transaction%';

B.作用:

2.3.3.2.內存相關

A.查詢語句: show tables like 'events_transaction%';

 

2.3.3.3. 等待事件記錄相關

A.查詢語句:show tables like 'events_wait%';

 

+-----------------------------------------------+

| Tables_in_performance_schema (%wait%)         |

+-----------------------------------------------+

| events_waits_current                          |

| events_waits_history                          |

| events_waits_history_long                     |

| events_waits_summary_by_account_by_event_name |

| events_waits_summary_by_host_by_event_name    |

| events_waits_summary_by_instance              |

| events_waits_summary_by_thread_by_event_name  |

| events_waits_summary_by_user_by_event_name    |

| events_waits_summary_global_by_event_name    

 

2.3.3.4. 階段事件記錄相關

A.查詢語句:show tables like 'events_stage%';

都是events_stages_* 開頭的表

 

 

2.3.4. 運行時配置

2.3.4.1. 開啓配置

A.在引擎啓動時並非所有表instruments(事件採集項,在採集項的配置表中每一項都有一個開關字段YESNO)consumers(與採集項類似, YES就表示對應的表保存性能數據,爲NO就表示對應的表不保存性能數據)都啓用了。需要手動開啓收集配置。

B.打開等待事件的採集器配置項開關,需要修改setup_instruments 配置表中對應的採集器配置項

   開啓語句:UPDATE setup_instruments SET ENABLED = 'YES', TIMED = 'YES' where name  like 'wait%';

C.打開等待事件的保存表配置開關,修改修改setup_consumers 配置表

   開啓語句:UPDATE setup_consumers SET ENABLED = 'YES' where name like '%wait%';

 

D.其他事件都類似

 

2.3.5. 應用:監控查詢例子

2.3.5.1.查詢連接數據庫實例的線程連接數量及賬號

select * from performance_schema.accounts;

  1. current_connections :當前連接數
  2. total_connections:總連接數

2.3.5.2.查詢SQL執行時長的歷史記錄

 SELECT EVENT_ID, TRUNCATE(TIMER_WAIT/1000000000000,6) as Duration, SQL_TEXT   FROM performance_schema.events_statements_current where SQL_TEXT IS NOT NULL AND SQL_TEXT <> 'BEGIN';

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