天天看點

EXPLAIN sql優化方法(3)DERIVED

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

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

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

需要考慮的另一方面是,派生表需要被顯式處理,盡管隻是執行 explain 語句。是以如果在 from 字句中的 selelct 操作上犯了錯誤,例如忘記了寫上連接配接的條件,那麼 explain 可能會一直在運作。

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

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

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

EXPLAIN sql優化方法(3)DERIVED

mysql> select * from test where i=5 ;  

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

| i | j                                |  

| 5 | 0c88dedb358cd96c9069b73a57682a45 |  

1 row in set ( 0 .03 sec)  

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

EXPLAIN sql優化方法(3)DERIVED

mysql> select * from ( select * from test) t where i=5 ;  

1 row in set ( 1 min 40 .86 sec)  

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

EXPLAIN sql優化方法(3)DERIVED

mysql> create view v as select * from test;  

query ok, 0 rows affected ( 0 .08 sec)  

mysql> select * from v  where i=5 ;  

1 row in set ( 0 .10 sec)  

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

EXPLAIN sql優化方法(3)DERIVED

mysql> explain select * from v  where i=5 ;  

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

| id | select_type | table | type  | possible_keys | key      | key_len | ref   | rows | extra |  

|  1 | primary      | test  | const | primary        | primary | 4        | const |    1 |       |  

1 row in set ( 0 .02 sec)  

mysql> explain select * from ( select * from test) t where i=5 ;  

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

| id | select_type | table       | type | possible_keys | key   | key_len | ref  | rows    | extra       |  

|  1 | primary      | <derived2> | all   | null           | null | null     | null | 1638400 | using where |  

|  2 | derived     | test       | all   | null           | null | null     | null | 1638400 |             |  

2 rows in set ( 54 .90 sec)  

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

可以考慮使用臨時試圖來取代派生表 如果确實需要在 from 子句中使用到子查詢,可以考慮在查詢時建立試圖,當查詢完之後删除試圖。

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

EXPLAIN sql優化方法(3)DERIVED

explain  select sum(pdm.qty) pre_total,pd.pre_doc_id from prepare_doc pd  

left join pre_doc_item pdm on pd.pre_doc_id=pdm.pre_doc_id group by pd.pre_doc_id  

EXPLAIN sql優化方法(3)DERIVED