使用explain和show profile來分析SQL語句實現優化SQL語句

2021-01-10 韓淼燃

SQL語句優化是建立在慢查詢分析的基礎上,通過慢查詢定位有問題的SQL語句,關於慢查詢的介紹及其分析工具,可以參考[mysql慢查詢及慢查詢日誌分析工具]

一、通過explain查詢

1 用法:explain sql

2 作用:用於分析sql語句

(1)、id:執行explain的一個編號(沒有實際意義)

(2)、table:查詢的表名

(3)、select_type:查詢類型,是單表查詢、聯合查詢還是子查詢等 可能會出現以下值:

例子使用的表結構:

CREATE TABLE `mall_user`(`uid`int(12) NOT NULL AUTO_INCREMENT COMMENT '用戶ID',`account` varchar(20) NOT NULL COMMENT '帳號',`email` varchar(70) NOT NULL DEFAULT '' COMMENT '郵箱',`password`char(32) NOT NULL DEFAULT '' COMMENT '密碼',`mobile`char(11) NOT NULL DEFAULT '' COMMENT '手機號',`nickname` varchar(20) NOT NULL DEFAULT '' COMMENT '暱稱',`status`enum('UNCHECKED','DISABLED','INACTIVED','ACTIVED') NOT NULL DEFAULT 'UNCHECKED' COMMENT '狀態',`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '加入時間', PRIMARY KEY (`uid`), UNIQUE KEY `idx_account`(`account`), UNIQUE KEY `idx_email`(`email`), UNIQUE KEY `idx_mobile`(`mobile`), UNIQUE KEY `idx_nickname`(`nickname`), KEY `idx_status`(`status`), KEY `idx_ctime`(`create_time`)) ENGINE=InnoDB AUTO_INCREMENT=300004 DEFAULT CHARSET=utf8 COMMENT='用戶表';例1:simple簡單查詢:

(4). type:連接使用的類型(重要項) 顯示連接使用的類型,按最 優到最差的類型排序

例2:type為const:

例3:type為ref:

例3:type為all:(這種是要避免和優化的)

(5). prossible_keys:能在該表中使用哪些索引有助於查詢

(6). key:實際使用的索引

(7). key_len:索引的長度,在不損失精確性的情況 下,長度越短越好

(8). ref:索引的哪一列被使用了

(9). rows:返回的結果的行數

(10). Extra:其他說明

以下兩種情況說明:MYSQL 根本不能使用索引,效率會受到重大影響。應儘可能對此進行優化

二、通過show profile查看SQL執行過程

1、執行步驟

首先得開啟profiling

set profiling=1

其次是執行sql

最後通過show profile查看分析結果

可以看出上圖中的Sending data是佔用時間最長的部分,可能是原因的是查詢的數據量過大

2、查看SQL執行各階段的資源消耗情況:

用法:

show profile <type> [for QUERY <NUM>] ;

參數說明:

<type> 表示顯示的資源類型,可以使用以下的值:

<NUM>表示顯示哪條SQL(這個數字可以通過SHOW profiles的中取得,for Query 不填寫則表示最近執行的SQL)通過show profile查找出最消耗性能的階段,針對其進行優 化三、SQL語句優化

1、count語句優化

(1)count(*)與count(col)的情況下:

第一種情況:在沒有任何查詢條件的情況下:

count(*)

count(region):region是一個普通欄位,沒有任何索引

count(country):country是一個普通索引

得出的結論:在沒有where條件的情況下,速度由快到慢的是:(可以多次運行,查看結果) count(*) > count(索引欄位) > count(未索引欄位)第二種情況:在有查詢條件的情況下:

從結果可以得出以下結論:

在有where條件的情況下,速度由快到慢的是: count(where條件中包含的欄位) > count(*) > count(未索引欄位)count語句優化結論:在有where條件的情況下,儘量使用count(where條件中的查詢條件欄位),其次是使用count(),避免使用count(col);在沒有where條件的情況下,儘量使用count()2、max語句優化 在max欄位上添加索引,可以提高其查詢效率

實驗: 在沒有添加的索引的欄位使用max

添加索引後:

alter table population add index idx_population(population);

發現:添加索引後的,如果帶where條件,而且where條件與max的欄位不一致時,所花時間竟然比不帶where的多了幾個數量級的,而且比之間不加索引花的時間更多。這個得考慮一下是什麼原因。

3、子查詢優化 根據實際情況而定:

如果查詢的條件是以左表的主鍵為查詢條件的,使用IN子查詢更高效 - 如果查詢的條件不是以左表的主鍵為查詢條件的,使用聯接查詢更高效以一個用戶表和用戶與組關係表為例:用戶表結構如下:

CREATE TABLE `mall_user`(`uid`int(12) NOT NULL AUTO_INCREMENT COMMENT '用戶ID',`account` varchar(20) NOT NULL COMMENT '帳號',`email` varchar(70) NOT NULL DEFAULT '' COMMENT '郵箱',`password`char(32) NOT NULL DEFAULT '' COMMENT '密碼',`mobile`char(11) NOT NULL DEFAULT '' COMMENT '手機號',`nickname` varchar(20) NOT NULL DEFAULT '' COMMENT '暱稱',`status`enum('UNCHECKED','DISABLED','INACTIVED','ACTIVED') NOT NULL DEFAULT 'UNCHECKED' COMMENT '狀態',`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '加入時間', PRIMARY KEY (`uid`), UNIQUE KEY `idx_account`(`account`), UNIQUE KEY `idx_email`(`email`), UNIQUE KEY `idx_mobile`(`mobile`), UNIQUE KEY `idx_nickname`(`nickname`), KEY `idx_status`(`status`), KEY `idx_ctime`(`create_time`)) ENGINE=InnoDB AUTO_INCREMENT=300004 DEFAULT CHARSET=utf8 COMMENT='用戶表';

用戶與組關係表結構:

CREATE TABLE `mall_user_group_relation`(`group_id`int(12) NOT NULL COMMENT '組ID',`uid`int(12) NOT NULL COMMENT '用戶ID',`remark` varchar(50) NOT NULL DEFAULT '' COMMENT '備註', PRIMARY KEY (`group_id`,`uid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;

原查詢語句:

select*from mall_user AS user where uid in(select distinct uid from mall_user_group_relation);

修改為關聯查詢的語句:

select distinct(user.uid),account,email,password,mobile,nickname,status,create_time from mall_user AS user RIGHT JOIN mall_user_group_relation AS relation ON user.uid=relation.uid

4、儘量避免使用select *

只獲取必要的欄位,不需要的欄位可以不用獲取。select * 查詢一些不必要的數據,會造成系統資源的極大浪費,特別是查詢數據量較多的數據時。

5、總結:

在where條件、order by、group by中儘量使用已經索引的欄位查詢必要的欄位和限定的記錄數(limit)不要完全相信已有經驗,需要自己根據explain和show profile來檢測SQL的執行效率,進行針對性的優化

相關焦點

  • MySQL優化:學會使用show profile和trace分析慢查詢
    看本篇之前建議先看上篇:MySQL優化:定位慢查詢的兩種方法以及使用explain分析SQL在上一節我們學習了定位慢 SQL 及使用 explain 分析慢 SQL,我們也提到了分析慢 SQL 還有 show profile 和 trace 等方法,本節就重點補充學習這兩種方法。
  • 提升SQL語句性能的方法
    用具體案例進行SQL語句性能提升的方法。先用實際案例分析了優化SQL語句的方法,然後再結合nat123這個實際案例分析了如何實現外網訪問內網Mysql資料庫的方法。優化方法:優化的總體思路是拆分sql,將排序操作和查詢所有信息的操作分開。
  • 日進一步第三天,SQL語句之order by
    公眾號:輕鬆自由7799第一天的SELECT……FEOM……是最常用的查詢語句,數據分析之小白的第一條sql語句第二天的group by則是方便快捷分組語句數據分析之小白的第二條sql語句今天帶來的是ORDER BY---排序語句為了對檢索出的結果進行排序,一般我們就會用到ORDER BY了,它的含義是:根據欄位……進行排序。
  • 《MySQL慢查詢優化》之SQL語句及索引優化
    1、慢查詢優化方式伺服器硬體升級優化Mysql伺服器軟體優化資料庫表結構優化SQL語句及索引優化>本文重點關注於SQL語句及索引優化,關於其他優化方式以及索引原理等,請關注本人《MySQL慢查詢優化》系列博文。
  • sqltoy-orm-4.16.11 發版,部分功能優化
    的十四個關鍵特點:1、最簡最直觀的sql編寫方式(不僅僅是查詢語句),採用條件參數前置處理規整法,讓sql語句部分跟客戶端保持高度一致2、sql中支持注釋(規避了對hint特性的影響,知道hint嗎?搜oracle hint),和動態更新加載,便於開發和後期維護整個過程的管理3、支持緩存翻譯和反向緩存條件檢索(通過緩存將名稱匹配成精確的key),實現sql簡化和性能大幅提升4、支持快速分頁和分頁優化功能,實現分頁最高級別的優化,同時還考慮到了cte多個with as情況下的優化支持5、支持並行查詢6、根本杜絕sql注入問題,以後不需要討論這個話題7、支持行列轉換
  • MySQL show profile使用說明
    show profile 和 show profiles 命令用於展示SQL語句的資源使用情況,包括CPU的使用,CPU上下文切換,IO等待,內存使用等,這個命令對於分析某個SQL的性能瓶頸非常有幫助,藉助於show profile的輸出信息,能讓我們知道一個SQL在哪個階段耗時最長,消耗資源最多
  • PL/SQL developer工具的使用之談
    而通過insert語句是沒有這種情況的 plsql自帶的文本導入亂碼問題使用UltraEditVersion 9.0.5.1648可以看到sql window快捷關閉無效,建議還是不要用這麼老的版本Version 11.0.3.1770tablespace那不能索引
  • sql語句的學習,分組查詢、分頁查詢、模糊查詢
    自增長是auto_incrementdrop table 表名 刪除表show create table 表名 可以看出該表的結構和看資料庫結構類似欄位類型>sql插入語句規則圖片來自培訓機構插入數據在dos亂碼問題的解決將utf8改成gbk就ok,但是這個改變的是系統文件,不好,還有一種方式是set names gbk;使用這種方式很好
  • 工作中,我們經常用到哪些SQL語句呢?
    工作中我們基本上每天都要與資料庫打交道,資料庫的知識點呢也特別多,全部記住呢也是不可能的,也沒必要把所有的記住(有些語句命令可能我們一輩子都用不到)。所以呢在工作之餘,把工作中經常用到的一些語句整理出來,忘記的時候可以當做字典來查。個人在工作中用Oracle資料庫比較多,就以關係型資料庫Oracle為例進行整理,後面可能會整理一些非關係型資料庫,如mogodb之類的。
  • 不懂就問:SQL 語句中 where 條件後 寫上1=1 是什麼意思
    本文轉載自【微信公眾號:五角錢的程式設計師,ID:xianglin965】經微信公眾號授權轉載,如需轉載與原文作者聯繫程式設計師在編程過程中,經常會在代碼中使用到「where 1=1」,這是為什麼呢?語法規範我們在寫代碼的過程中,為了保證語法規範的時候,也會使用到where 1=1。
  • 女朋友都能看懂的,SQL優化乾貨
    是從1開始計算,如果沒有找到就直接返回0 ,所以可以使用如下sql:select * from teacher where INSTR(name,'老師')>02、使用了in和not in,會全表掃描普通查詢:
  • 醫院SQL資料庫系統語句優化
    本文提出的醫院資料庫系統性能優化是在己有的硬體設施升級、資料庫的物理設計、關係規範化等方面進行改進基礎之上,對SQL語句進行了有效的分析設計的問題,以使其加快執行速度,減少網絡傳輸,能更高效地工作,充分發揮系統的效率。1 合理使用索引提高資料庫查詢速度最有效的方法就是優化索引。
  • 大數據分析工程師入門9-Spark SQL
    使用RDD進行編程時,開發人員在採用不同的程式語言和不同的方式開發應用程式時,其應用程式的性能千差萬別,但如果使用DataFrame和Dataset進行開發時,資深開發人員和初級開發人員開發的程序性能差異很小,這是因為SparkSQL 內部使用Catalyst optimizer 對執行計劃做了很好的優化。
  • 如何使用 SQL Server FILESTREAM 存儲非結構化數據?
    使用SQL Server 配置管理器在SQL Server級別啟用FILESTREAM啟用FILESTREAM的第二個級別是SQL Server Instance(實例)級別。通過執行腳本1中提供的T-SQL腳本來實現。
  • mybatis 框架 SQL映射文件之SQL片段
    今天分享得是動態 sqlif 標籤和 where 標籤還記得我們上一下次分享的 mapper 的特性中有一個就是傳入包裝類的查詢語句嗎?這樣 SQL 語句就出錯了,當我們使用 <where> 標籤的時候,如果遇到的第一個條件,出現 and 的時候,就會把這個 and 去掉。
  • SQL Server資料庫和Oracle行轉列的特殊方案描述
    為了簡化問題,我們且看如下查詢出來的數據,您不必關心表的設計以及sql語句: 對於有些業務來說,數據在表中的存儲和其最終的Grid表現恰好相當於把源表倒轉,那麼這個時候我們就碰到了如何把行轉化為列的問題,為了簡化問題,我們且看如下查詢出來的數據,您不必關心表的設計以及sql語句: 假設用到的sql語句為: SELECT [姓名],[時代],[金錢
  • sqltoy-orm-4.17.5 發布,支持 QueryExecutor 中定義分庫分表
    的十四個關鍵特點:1、最簡最直觀的sql編寫方式(不僅僅是查詢語句),採用條件參數前置處理規整法,讓sql語句部分跟客戶端保持高度一致2、sql中支持注釋(規避了對hint特性的影響,知道hint嗎?搜oracle hint),和動態更新加載,便於開發和後期維護整個過程的管理3、支持緩存翻譯和反向緩存條件檢索(通過緩存將名稱匹配成精確的key),實現sql簡化和性能大幅提升4、支持快速分頁和分頁優化功能,實現分頁最高級別的優化,同時還考慮到了cte多個with as情況下的優化支持5、支持並行查詢6、根本杜絕sql注入問題,以後不需要討論這個話題7、支持行列轉換
  • sqltoy-orm-4.16.16 發版,並行查詢場景增強、級聯增加排序
    致謝:       感謝廣大網友的積極使用和反饋,提出了非常好的意見,讓sqltoy再次變得嚴謹和細膩!
  • 淺談開啟magic_quote_gpc後的sql注入攻擊與防範
    開啟magic_quote_gpc=on之後,能實現addslshes()和stripslashes()這兩個函數的功能。SQL語句:$sql="select * from users where username=$name and password='$pwd'";注意:變量$name沒加引號此時,在地址欄中輸入username=admin%23,則合成後的sql語句為:select * from users where username='admin\' #' and password='
  • 最詳細的SQL注入相關的命令整理
    在這些參數中,"/L:system"和"/R:user"參數是可選項,如果不使用這兩個參數,註冊表編輯器則認為是對WINDOWS目錄下的"system.dat"和"user.dat"文件進行操作。如果是通過從軟盤啟動並進入DOS,那麼就必須使用"/L"和"/R"參數來指定"system.dat"和"user.dat"文件的具體路徑,否則註冊表編輯器將無法找到它們。