MySQL 查詢 select * from table where id in 如何提高效率?
阿新 • • 發佈:2019-02-18
例句:select
* from a where id in (select id from b );
對於這條sql語句它的執行計劃其實並不是先查詢出b表的所有id,然後再與a表的id進行比較。
mysql會把in子查詢轉換成exists相關子查詢,所以它實際等同於這條sql語句:select * from a where exists(select * from b where b.id=a.id );
而exists相關子查詢的執行原理是: 迴圈取出a表的每一條記錄與b表進行比較,比較的條件是a.id=b.id . 看a表的每條記錄的id是否在b表存在,如果存在就行返回a表的這條記錄。
exists查詢有什麼弊端?
由exists執行原理可知,a表(外表)使用不了索引,必須全表掃描,因為是拿a表的資料到b表查。而且必須得使用a表的資料到b表中查(外表到裡表中),順序是固定死的。
如何優化?
把查詢修改成inner join連線查詢:select * from a inner join b on a.id=b.id;
SELECT a.good_num, a.cal_date, a.count,a.apply_date, a.name, a.class_num
FROM table1 a
inner join
( SELECT max(id) id
FROM table1
where name = '金屬製品有限公司' GROUP BY num ) b
on a.id=b.id
where a.count >= 10000
對於這條sql語句它的執行計劃其實並不是先查詢出b表的所有id,然後再與a表的id進行比較。
mysql會把in子查詢轉換成exists相關子查詢,所以它實際等同於這條sql語句:select * from a where exists(select * from b where b.id=a.id );
而exists相關子查詢的執行原理是: 迴圈取出a表的每一條記錄與b表進行比較,比較的條件是a.id=b.id . 看a表的每條記錄的id是否在b表存在,如果存在就行返回a表的這條記錄。
exists查詢有什麼弊端?
由exists執行原理可知,a表(外表)使用不了索引,必須全表掃描,因為是拿a表的資料到b表查。而且必須得使用a表的資料到b表中查(外表到裡表中),順序是固定死的。
如何優化?
把查詢修改成inner join連線查詢:select * from a inner join b on a.id=b.id;
可用EXPLAIN EXTENDED或者DESC來檢視SQL執行計劃來分析,下面是實際優化SQL,欄位和表名做了處理
優化前
SELECT a.good_num, a.cal_date, a.count,a.apply_date, a.name, a.class_num
FROM table1
where id in (
SELECT max(id) id
FROM table1
where name = '金屬製品有限公司' GROUP BY num
)
優化後
SELECT a.good_num, a.cal_date, a.count,a.apply_date, a.name, a.class_num
FROM table1 a
inner join
( SELECT max(id) id
FROM table1
where name = '金屬製品有限公司' GROUP BY num ) b
on a.id=b.id
where a.count >= 10000