mysql的子查詢
子查詢的執行方式不同於oracle,它不會首先得到一個in 列表,然後通過這些值去進行過濾:
改進方法,重寫查詢或者先取出列表,然後再查詢。
MySQL tries to “help” the subquery by
pushing a correlation into it from the outer table, which it thinks will let the subquery
find rows more efficiently. It rewrites the query as follows:
pushing a correlation into it from the outer table, which it thinks will let the subquery
find rows more efficiently. It rewrites the query as follows:
mysql> explain
-> SELECT * FROM sakila.film
-> WHERE film_id IN(
-> SELECT film_id FROM sakila.film_actor WHERE actor_id = 1);
+----+--------------------+------------+--------+------------------------+---------+---------+------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+------------+--------+------------------------+---------+---------+------------+------+-------------+
| 1 | PRIMARY | film | ALL | NULL | NULL | NULL | NULL | 952 | Using where |
| 2 | DEPENDENT SUBQUERY | film_actor | eq_ref | PRIMARY,idx_fk_film_id | PRIMARY | 4 | const,func | 1 | Using index |
+----+--------------------+------------+--------+------------------------+---------+---------+------------+------+-------------+
2 rows in set (0.60 sec)
-> SELECT * FROM sakila.film
-> WHERE film_id IN(
-> SELECT film_id FROM sakila.film_actor WHERE actor_id = 1);
+----+--------------------+------------+--------+------------------------+---------+---------+------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+------------+--------+------------------------+---------+---------+------------+------+-------------+
| 1 | PRIMARY | film | ALL | NULL | NULL | NULL | NULL | 952 | Using where |
| 2 | DEPENDENT SUBQUERY | film_actor | eq_ref | PRIMARY,idx_fk_film_id | PRIMARY | 4 | const,func | 1 | Using index |
+----+--------------------+------------+--------+------------------------+---------+---------+------------+------+-------------+
2 rows in set (0.60 sec)
mysql> explain
-> SELECT * FROM sakila.film
-> WHERE EXISTS (
-> SELECT * FROM sakila.film_actor WHERE actor_id = 1
-> AND film_actor.film_id = film.film_id);
+----+--------------------+------------+--------+------------------------+---------+---------+---------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+------------+--------+------------------------+---------+---------+---------------------------+------+-------------+
| 1 | PRIMARY | film | ALL | NULL | NULL | NULL | NULL | 952 | Using where |
| 2 | DEPENDENT SUBQUERY | film_actor | eq_ref | PRIMARY,idx_fk_film_id | PRIMARY | 4 | const,sakila.film.film_id | 1 | Using index |
+----+--------------------+------------+--------+------------------------+---------+---------+---------------------------+------+-------------+
2 rows in set (0.02 sec)
-> SELECT * FROM sakila.film
-> WHERE EXISTS (
-> SELECT * FROM sakila.film_actor WHERE actor_id = 1
-> AND film_actor.film_id = film.film_id);
+----+--------------------+------------+--------+------------------------+---------+---------+---------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+------------+--------+------------------------+---------+---------+---------------------------+------+-------------+
| 1 | PRIMARY | film | ALL | NULL | NULL | NULL | NULL | 952 | Using where |
| 2 | DEPENDENT SUBQUERY | film_actor | eq_ref | PRIMARY,idx_fk_film_id | PRIMARY | 4 | const,sakila.film.film_id | 1 | Using index |
+----+--------------------+------------+--------+------------------------+---------+---------+---------------------------+------+-------------+
2 rows in set (0.02 sec)
According to the EXPLAIN output, MySQL will table-scan the film table and execute
the subquery for each row it finds. This won’t cause a noticeable performance hit on
small tables, but if the outer table is very large, the performance will be extremely
bad. Fortunately, it’s easy to rewrite such a query as a JOIN:
mysql> SELECT film.* FROM sakila.film
-> INNER JOIN sakila.film_actor USING(film_id)
-> WHERE actor_id = 1;
Another good optimization is to manually generate the IN( ) list by executing the
subquery as a separate query with GROUP_CONCAT( ). Sometimes this can be faster than
a JOIN.
MySQL has been criticized thoroughly for this particular type of subquery execution
plan. Although it definitely needs to be fixed, the criticism often confuses two different
issues: execution order and caching. Executing the query from the inside out is
one way to optimize it; caching the inner query’s result is another. Rewriting the
query yourself lets you take control over both aspects. Future versions of MySQL
should be able to optimize this type of query much better, although this is no easy
task. There are very bad worst cases for any execution plan, including the inside-out
execution plan that some people think would be simple to optimize.
the subquery for each row it finds. This won’t cause a noticeable performance hit on
small tables, but if the outer table is very large, the performance will be extremely
bad. Fortunately, it’s easy to rewrite such a query as a JOIN:
mysql> SELECT film.* FROM sakila.film
-> INNER JOIN sakila.film_actor USING(film_id)
-> WHERE actor_id = 1;
Another good optimization is to manually generate the IN( ) list by executing the
subquery as a separate query with GROUP_CONCAT( ). Sometimes this can be faster than
a JOIN.
MySQL has been criticized thoroughly for this particular type of subquery execution
plan. Although it definitely needs to be fixed, the criticism often confuses two different
issues: execution order and caching. Executing the query from the inside out is
one way to optimize it; caching the inner query’s result is another. Rewriting the
query yourself lets you take control over both aspects. Future versions of MySQL
should be able to optimize this type of query much better, although this is no easy
task. There are very bad worst cases for any execution plan, including the inside-out
execution plan that some people think would be simple to optimize.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/758322/viewspace-680933/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MySQL子查詢MySql
- MYsql 子查詢MySql
- MySQL聯結查詢和子查詢MySql
- MySQL之連線查詢和子查詢MySql
- 【MySQL】檢視&子查詢MySql
- MySQL 相關子查詢MySql
- [MYSQL -14]使用子查詢MySql
- 【MySQL】子查詢之一MySql
- MySQL子查詢的優化薦MySql優化
- mysql-分組查詢-子查詢-連線查詢-組合查詢MySql
- 子查詢-表子查詢
- MySQL全面瓦解11:子查詢和組合查詢MySql
- MySQL資料庫基礎——多表查詢:子查詢MySql資料庫
- MYSQL學習筆記26: 多表查詢|子查詢MySql筆記
- MYSQL學習筆記25: 多表查詢(子查詢)[標量子查詢,列子查詢]MySql筆記
- SQL查詢的:子查詢和多表查詢SQL
- 沒想到mysql的子查詢這麼弱MySql
- 生產庫中遇到mysql的子查詢MySql
- mysql子查詢的缺陷以及5.6的優化MySql優化
- 關於mysql 子查詢中 使用 limitMySqlMIT
- Mysql中的巢狀子查詢問題QSBSMySql巢狀
- MySql中limit子查詢的解決辦法MySqlMIT
- 複雜查詢—子查詢
- mysql求交集:UNION ALL合併查詢,inner join內連線查詢,IN/EXISTS子查詢MySql
- mysql sql_safe_updates 不支援子查詢的更新。MySql
- MySQL中in(獨立子查詢)的執行計劃MySql
- 《MySQL 入門教程》第 19 篇 子查詢MySql
- MySQL第六篇:索引與子查詢MySql索引
- mysql 的delete from where 子查詢的一些限制MySqldelete
- 相關子查詢&非相關子查詢概念
- MySQL 優化五(關聯查詢子查詢以及 in 的效率問題)(高階篇)MySql優化
- 子查詢的典型例子
- 子串查詢
- 使用子查詢
- oracle子查詢Oracle
- 查詢子串
- 子查詢分解
- 11子查詢