1. 程式人生 > >MySQL SQL優化之 執行計劃 explain

MySQL SQL優化之 執行計劃 explain

1.環境

OS: CentOS 6.5 x64

MySQL: 5.6 for Linux (x86_64)

2.優化第一步

拿到一個慢SQL時,第一步就是看執行計劃並權衡是否可以加索引,就是這麼簡單,不要被高深莫測的人給矇住說什麼有更好的方法,告訴各位同學:沒有更好的方法,看執行計劃和權衡加索引就是最好的方法。然後才是考慮各種別的優化方案。

3.SQL優化注意幾點

1).注意函式呼叫的次數,避免每行都呼叫一次

2).避免全表掃描,尤其是大表

3).定期執行Analyze Table

4).熟悉各個引擎的調優技術、索引技術和配置引數。主要引擎是MyISAM、InnoDB、MEMORY。

5).如果一個SQL太複雜,就拆分成一塊一塊地優化

6).調記憶體

7).注意鎖

4.執行計劃 EXPLAIN

要使用執行計劃,首先要讀懂執行計劃,然後通過改寫SQL和索引技術來改進執行計劃。

MySQL5.6.3之前只有 SELECT 可以生成執行計劃,5.6.3及之後的版本SELECT DELETE INSERT REPLACE UPDATE都可以生成執行計劃。

explain語法:

{EXPLAIN | DESCRIBE | DESC}
    tbl_name [col_name | wild]

{EXPLAIN | DESCRIBE | DESC}
    [explain_type
] explainable_stmt explain_type: { EXTENDED | PARTITIONS | FORMAT = format_name } format_name: { TRADITIONAL | JSON } explainable_stmt: { SELECT statement | DELETE statement | INSERT statement | REPLACE statement | UPDATE statement }
看到了吧,檢視執行計劃不只explain命令,desc也可以,結果一樣。

mysql> desc select * from p_range where id=12;
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table   | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | p_range | const | PRIMARY       | PRIMARY | 4       | const |    1 | NULL  |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)


mysql> desc extended

select * from p_range where id=12;
+----+-------------+---------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table   | type  | possible_keys | key     | key_len | ref   | rows |filtered | Extra |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | p_range | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | NULL  |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.02 sec)

有一個warning,可以看看

mysql> show warnings;
+-------+------+------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                  |
+-------+------+------------------------------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select '12' AS `id`,'員工JONES' AS `name` from `test`.`p_range` where 1   |
+-------+------+------------------------------------------------------------------------------------------+
1 row in set (0.04 sec)
警告資訊顯示優化器優化後執行的SQL。再看一個複雜點的:

mysql> desc extended select * from emp where deptno in (select deptno from dept where deptno=20);
+----+-------------+-------+-------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra       |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+----------+-------------+
|  1 | SIMPLE      | dept  | const | PRIMARY       | PRIMARY | 1       | const |    1 |   100.00 | Using index |
|  1 | SIMPLE      | emp   | ALL   | NULL          | NULL    | NULL    | NULL  |   14 |   100.00 | Using where |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+----------+-------------+
2 rows in set, 1 warning (0.00 sec)


mysql> show warnings;
+-------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                                                                                                                                                                                                                                                                 |
+-------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select `test`.`emp`.`empno` AS `empno`,`test`.`emp`.`ename` AS `ename`,`test`.`emp`.`job` AS `job`,`test`.`emp`.`mgr` AS `mgr`,`test`.`emp`.`hiredate` AS `hiredate`,`test`.`emp`.`sal` AS `sal`,`test`.`emp`.`comm` AS `comm`,`test`.`emp`.`deptno` AS `deptno` from `test`.`dept` join `test`.`emp` where (`test`.`emp`.`deptno` = 20) |
+-------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

從警告裡可以看出優化器最終將*替換成所有的列名,這不但增加了sql文字的長度佔用更多記憶體,還會使返回的資料量增大,所以在select列表裡一定要寫明所選列的列名,尤其當表中列特別多時更應寫出列名,只選要檢視的列。



mysql> desc partitions select * from p_range where id=12;
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table   | partitions | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | p_range | p0         | const | PRIMARY       | PRIMARY | 4       | const |    1 | NULL  |
+----+-------------+---------+------------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)

以下摘錄一部分:

EXPLAIN Output Columns

This section describes the output columns produced by EXPLAIN. Later sections provide additional information about the type and Extra columns.

Each output row from EXPLAIN provides information about one table. Each row contains the values summarized in Table 8.1, “EXPLAIN Output Columns”, and described in more detail following the table. Column names are shown in the table's first column; the second column provides the equivalent property name shown in the output when FORMAT=JSON is used.

Table 8.1 EXPLAIN Output Columns

Column JSON Name Meaning
id select_id The SELECT identifier
None The SELECT type
table table_name The table for the output row
partitions The matching partitions
type access_type The join type
possible_keys The possible indexes to choose
key key The index actually chosen
key_length The length of the chosen key
ref ref The columns compared to the index
rows rows Estimate of rows to be examined
filtered Percentage of rows filtered by table condition
Extra None Additional information

Note

JSON properties which are NULL are not displayed in JSON-formatted EXPLAIN output.

  •  id (JSON name: select_id)

    The SELECT identifier. This is the sequential number of the SELECT within the query. The value can be NULL if the row refers to the union result of other rows. In this case, the table column shows a value like <unionM,N> to indicate that the row refers to the union of the rows with id values of M and N.

  •  select_type (JSON name: none)

    The type of SELECT, which can be any of those shown in the following table. A JSON-formatted EXPLAIN exposes the SELECT type as a property of aquery_block, unless it is SIMPLE or PRIMARY. The JSON names (where applicable) are also shown in the table.

    select_type Value JSON Name Meaning
    SIMPLE None Simple SELECT (not using UNION or subqueries)
    PRIMARY None Outermost SELECT
    UNION None Second or later SELECT statement in a UNION
    DEPENDENT UNION dependent (true) Second or later SELECT statement in a UNION, dependent on outer query
    UNION RESULT union_result Result of a UNION.
    SUBQUERY None First SELECT in subquery
    DEPENDENT SUBQUERY dependent (true) First SELECT in subquery, dependent on outer query
    DERIVED None Derived table SELECT (subquery in FROM clause)
    MATERIALIZED materialized_from_subquery Materialized subquery
    UNCACHEABLE SUBQUERY cacheable (false) A subquery for which the result cannot be cached and must be re-evaluated for each row of the outer query
    UNCACHEABLE UNION cacheable (false) The second or later select in a UNION that belongs to an uncacheable subquery (seeUNCACHEABLE SUBQUERY)

    DEPENDENT typically signifies the use of a correlated subquery. See Section 13.2.10.7, “Correlated Subqueries”.

    DEPENDENT SUBQUERY evaluation differs from UNCACHEABLE SUBQUERY evaluation. For DEPENDENT SUBQUERY, the subquery is re-evaluated only once for each set of different values of the variables from its outer context. For 

    相關推薦

    MySQL SQL優化 執行計劃 explain

    1.環境 OS: CentOS 6.5 x64 MySQL: 5.6 for Linux (x86_64) 2.優化第一步 拿到一個慢SQL時,第一步就是看執行計劃並權衡是否可以加索引,就是這麼簡單,不要被高深莫測的人給矇住說什麼有更好的方

    MySQL SQL優化‘%’

    sql優化設計索引的主要目的就是幫助我們快速獲取查詢結果,而以%開頭的like查詢則不能夠使用B-Tree索引。考慮到innodb的表都是聚簇表(類似於oracle中的索引組織表),且二級索引葉節點中記錄的結構為(索引字段->主鍵字段),我們可以通過改寫sql(mysql優化器比較笨,需要給它足夠的提示

    讓天下沒有難用的資料庫 » mysql sql優化straight_join

    在oracle中可以指定的表連線的hint有很多:ordered hint 指示oracle按照from關鍵字後的表順序來進行連線;leading hint 指示查詢優化器使用指定的表作為連線的首表,即驅動表;use_nl hint指示查詢優化器使用nested loops方式連線指定表和其他行源,

    讓天下沒有難用的資料庫 » MySql sql優化order by desc/asc limit M

    Order by desc/asc limit M是我在mysql sql優化中經常遇到的一種場景,其優化原理也非常的簡單,就是利用索引的有序性,優化器沿著索引的順序掃描,在掃描到符合條件的M行資料後,停止掃描;看起來非常的簡單,但是我經常看到很多效能較差的sql沒有利用這個優化規律,下面將結合一些

    MySQL SQL優化覆蓋索引

    內容概要 利用主索引提升SQL的查詢效率是我們經常使用的一個技巧,但是有些時候MySQL給出的執行計劃卻完全出乎我們的意料,我們預想MySQL會通過索引掃描完成查詢,但是MySQL給出的執行計劃卻是通過全表掃描完成查詢的,其中的某些場景我們可以利用覆蓋索引進行優化。

    ORACLE資料庫SQL優化--->如何執行計劃執行順序

    建議安裝(10g即以上版本上)xplan package,XPALN包其實是對DBMS_XPLAN包的封裝,使用XPLAN包就可以很清晰的看到執行計劃的執行順序。 安裝很簡單:其中xplan.sql_.txt可以到如下的網站下載: [[email protec

    Mysql SQL優化系列——執行計劃連線方式淺釋

    關係庫SQL調優中,雖然思路都是一樣的,具體方法和步驟也是大同小異,但細節卻不容忽視,尤其是執行計劃的具體細節的解讀中,各關係庫確實有區別,特別是mysql資料庫,與其他關係庫的差別更大些,下面,我們僅就SQL執行計劃中最常見的連線方式,做以下簡要介紹和說明。 system : a syst

    MySQL系列-優化explain執行計劃詳解

    1.id介紹 這個id不是主鍵的意思,他是用來標識select查詢的序列號,包含一組數字,表示查詢中執行select子句或者操作表的順序。 會出現以下情況: id相同:按從上到下順序執行 id不同:id值越大,優先順序越高,越先被執行 id相同不同的同時存在:優先執

    mysql sql優化sql執行計劃

    mysql 執行計劃SQL優化禁用SELECT *使用SELECT COUNT(*) 統計行數盡量少運算盡量避免全表掃描,如果可以,在過濾列建立索引盡量避免在WHERE子句對字段進行NULL判斷盡量避免在WHERE子句使用!= 或者<>盡量避免在WHERE子句使用OR連接盡量避免對字段進行表達式計

    MySQL優化執行計劃開始(explain超詳細)

    ### 前言 小夥伴一定遇到過這樣反饋:這頁面載入資料太慢啦,甚至有的超時了,使用者體驗極差,需要趕緊優化; 反饋等同於投訴啊,多有幾次,估計領導要找你談話啦。 於是不得不停下手裡頭的活,趕緊進行排查,最終可能是程式處理的問題、也可能是併發量大導致排隊問題、也可能是SQL查詢效能導致等;而在很多時候,S

    SQL Server 性能調優 執行計劃(Execution Plan)調優

    mod isp jsb see 環境 指定 logical term alt SQL Server 存在三種 Join 策略:Hash Join,Merge Join,Nested Loop Join。 Hash Join:用來處理沒有排過序/沒有索引的數據,它在內存中把

    MySQL查詢優化explain的深入解析

    extra lin sub const query gin alt com nec 本篇文章是對MySQL查詢優化中的explain進行了詳細的分析介紹,需要的朋友參考下 在分析查詢性能時,考慮EXPLAIN關鍵字同樣很管用。EXPLAIN關鍵字一般放在SELECT查

    MySQL(二) —— MySQL效能優化 SQL語句優化

              SQL語句優化   MySQL優化的目的   1、避免出現頁面訪問錯誤:或由於資料庫連線超時 timeout 產生頁面5xx錯誤;或由於慢查詢造成頁面無法載入;或由於阻        塞造成資料無法提交;

    Hive執行計劃分析(explain)

    Hive是通過把sql轉換成對應mapreduce程式,然後提交到Hadoop上執行,檢視具體的執行計劃可以通過執行explain sql知曉 一條sql會被轉化成由多個階段組成的步驟,每個步驟有執行順序和依賴關係,可以稱之為有向無環圖(DAG:Directed Acyclic Graph) 這

    檢視一個正在執行sql執行計劃(explain for connection processlist_id)

    線上往往會出現如下這種情況 一條sql很慢,但是寫的太長了,沒辦法複製出來,但是想看他的執行計劃,怎麼辦呢?幸好MySQL5.7提供了額外的explain方法 | 25977372 | ashe | 111.111.1.111:41102 | ashe

    MySQL(二) —— MySQL效能優化 SQL語句優化

              SQL語句優化 MySQL優化的目的   1、避免出現頁面訪問錯誤:或由於資料庫連線超時 timeout 產生頁面5xx錯誤;或由於慢查詢造成頁面無法載入;或由於阻        塞造成資料無法提交;   2、增加資料庫的穩定性:避免由於低效查詢

    通過分析SQL語句的執行計劃優化SQL(總結)

    如何幹預執行計劃 - - 使用hints提示 基於代價的優化器是很聰明的,在絕大多數情況下它會選擇正確的優化器,減輕了DBA的負擔。但有時它也聰明反被聰明誤,選擇了很差的執行計劃,使某個語句的執行變得奇慢無比。此時就需要DBA進行人為的干預,告訴優化器使用我們指定的存取路徑或連線型別生成執行計劃,從而使

    SQL優化一則MySQL中的DELETE、UPDATE 子查詢的鎖機制失效案例

    關注“資料和雲”,精彩不容錯過前言開發與維護人員避免不了與 in/exists、not in/n

    sql server 資料庫優化--顯示執行計劃 你真的知道索引使用???

    首先在PRID欄位上建立非聚集索引。 CREATE UNIQUE NONCLUSTERED INDEX UNC_PRID ON PerformanceIssue (PRID) GO 執行下面語句並檢視執行計劃的結果。 Select PRID, PRCode, PRDesc From Perform

    性能測試四十一:sql案例sql配置、執行計劃和索引

    xpl 通過 數據庫 data 設計 增加 應該 windows 情況下 MYSQL 慢查詢使用方法MYSQL慢查詢介紹分析MySQL語句查詢性能的問題時候,可以在MySQL記錄中查詢超過指定時間的語句,我們將超過指定時間的SQL語句查詢稱為“慢查詢&rdquo