EXPLAIN sql優化方法(3)DERIVED


派生表和視圖的性能

從MySQL 4.1開始,它已經支持派生表、聯機視圖或者基本的FROM從句的子查詢。

這些特性之間彼此相關,但是它們之間的性能比較如何呢?

MySQL 5.0 中的派生表似乎和視圖實現的方式不同,盡管我從合並的代碼基數來看覺得在查詢優化上應該是一樣的。

派生表仍然以臨時表的方式顯式地處理,而且還是沒有索引的臨時表(因此最好不要像在例子中那樣連接2個派生表)

需要考慮的另一方面是,派生表需要被顯式處理,盡管只是執行 EXPLAIN 語句。因此如果在 FROM 字句中的 SELELCT 操作上犯了錯誤,例如忘記了寫上連接的條件,那么 EXPLAIN 可能會一直在運行。

視圖則不同,它無需被顯式處理,只是把查詢簡單地重寫了一下。只有在無法合並查詢或者試圖創建者請求時才需要被顯式處理。

這意味着它們在性能上的差別如下:

在基本的表上執行有索引 的查詢,這非常快

Java代碼   收藏代碼
  1. mysql> SELECT * FROM test WHERE i=5 ;  
  2. +---+----------------------------------+  
  3. | i | j                                |  
  4. +---+----------------------------------+  
  5. 5 | 0c88dedb358cd96c9069b73a57682a45 |  
  6. +---+----------------------------------+  
  7. 1 row IN SET ( 0 .03 sec)  

在派生表上做同樣的查詢,則如老牛拉破車

Java代碼   收藏代碼
  1. mysql> SELECT * FROM ( SELECT * FROM test) t WHERE i=5 ;  
  2. +---+----------------------------------+  
  3. | i | j                                |  
  4. +---+----------------------------------+  
  5. 5 | 0c88dedb358cd96c9069b73a57682a45 |  
  6. +---+----------------------------------+  
  7. 1 row IN SET ( 1 min 40 .86 sec)  

在視圖上查詢,又快起來了 

Java代碼   收藏代碼
  1. mysql> CREATE VIEW v AS SELECT * FROM test;  
  2. Query OK, 0 rows affected ( 0 .08 sec)  
  3.    
  4. mysql> SELECT * FROM v  WHERE i=5 ;  
  5. +---+----------------------------------+  
  6. | i | j                                |  
  7. +---+----------------------------------+  
  8. 5 | 0c88dedb358cd96c9069b73a57682a45 |  
  9. +---+----------------------------------+  
  10. 1 row IN SET ( 0 .10 sec)  

下面的2條EXPLAIN結果也許會讓你很驚訝

Java代碼   收藏代碼
  1. mysql> EXPLAIN SELECT * FROM v  WHERE i=5 ;  
  2. +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+  
  3. | id | select_type | TABLE | type  | possible_keys | KEY      | key_len | ref   | rows | Extra |  
  4. +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+  
  5. |  1 | PRIMARY      | test  | const | PRIMARY        | PRIMARY | 4        | const |    1 |       |  
  6. +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+  
  7. 1 row IN SET ( 0 .02 sec)  
  8.    
  9. mysql> EXPLAIN SELECT * FROM ( SELECT * FROM test) t WHERE i=5 ;  
  10. +----+-------------+------------+------+---------------+------+---------+------+---------+-------------+  
  11. | id | select_type | TABLE       | type | possible_keys | KEY   | key_len | ref  | rows    | Extra       |  
  12. +----+-------------+------------+------+---------------+------+---------+------+---------+-------------+  
  13. |  1 | PRIMARY      | <derived2> | ALL   | NULL           | NULL | NULL     | NULL | 1638400 | USING WHERE |  
  14. |  2 | DERIVED     | test       | ALL   | NULL           | NULL | NULL     | NULL | 1638400 |             |  
  15. +----+-------------+------------+------+---------------+------+---------+------+---------+-------------+  
  16. 2 rows IN SET ( 54 .90 sec)  

避免使用派生表 -- 如果可能,最好采用其他方式來編寫查詢語句,大部分情況都比派生表來的快。很多情況下,甚至連獨立的臨時表都來的快,因為可以適當增加索引。

可以考慮使用臨時試圖來取代派生表 如果確實需要在 FROM 子句中使用到子查詢,可以考慮在查詢時創建試圖,當查詢完之后刪除試圖。

不適合多表視圖,多表時用派生表取代視圖

Java代碼   收藏代碼
  1. explain  select sum(pdm.qty) pre_total,pd.pre_doc_id from prepare_doc pd  
  2. left join pre_doc_item pdm on pd.pre_doc_id=pdm.pre_doc_id group by pd.pre_doc_id  


 
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM