天天看点

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