1. IN在MySQL中是先查詢子查詢的表,然后將內表與外表進行一個笛卡爾積,再按條件進行篩選,在內表數據相對較小時,IN的速度較快
2.用IN效率低的原因
- 跟實際的關聯數據類型
- 列的索引
- 表數據大小
- 等等情況
3.使用EXISTS來替代IN
-
EXISTS是先將外表作為驅動表,每次都是去查詢外表數據,然后再進行判斷,如果成立就將結果保留,否則則刪除該行
-
與IN的區別就在於:如果子查詢得出的結果集記錄較少,主查詢中的表較大且又有索引時應該用in, 反之如果外層的主查詢記錄較少,子查詢中的表大,又有索引時使用exists。
-
驅動順序的不同:IN先執行子查詢,EXISTS以外層為驅動表,先被訪問
-
邏輯:IN是以外表和內表進行連接,EXISTS是對外表的循環
-
使用 not in 和 not exists
- not in會造成子查詢的全表掃描,沒使用到索引,而not exists的子查詢仍然能用上索引,理論上無論內表大還是外表大,not exists都會效率更高,但實際上不一定
-
案例:
-
--users表有1000條記錄,id自增,id都大於0 select * from users where exists (select * from users limit 0); --輸出多少條記錄? select * from users where exists (select * from users where id < 0); --輸出多少條記錄? 答案(請選中查看): 10000條 0條 原因:exists查詢的本質,只要碰到有記錄,則返回true;所以limit根本就不會去管,或者說執行不到 -
exists可以完全代替in嗎? 不能。 例如: -沒有關聯字段的情況:枚舉常量 select * from areas where id in (4, 5, 6); -沒有關聯字段的情況:這樣exists對子查詢,要么全true,要么全false select * from areas where id in (select city_id from deals where deals.name = 'xxx'); -
在許多基於基礎表的查詢中,為了滿足一個條件,往往需要對另一個表進行聯接。 在這種情況下,使用exists(或not exists)通常將提高查詢的效率。 舉例: (低效) select ... from table1 t1 where t1.id > 10 and pno in (select no from table2 where name like 'www%'); (高效) select ... from table1 t1 where t1.id > 10 and exists (select 1 from table2 t2 where t1.pno = t2.no and name like 'www%'); -
用exists替換distinct: 當提交一個包含一對多表信息的查詢時,避免在select子句中使用distinct. 一般可以考慮用exists替換 舉例: (低效) select distinct d.dept_no, d.dept_name from t_dept d, t_emp e where d.dept_no = e.dept_no; (高效) select d.dept_no, d.dept_name from t_dept d where exists (select 1 from t_emp where d.dept_no = e.dept_no); exists使查詢更為迅速,因為RDBMS核心模塊將在子查詢的條件一旦滿足后,立刻返回結果. -
用表連接替換exists: 通常來說,采用表連接的方式比exists更有效率。 舉例: (低效) select ename from emp e where exists (select 1 from dept where dept_no = e.dept_no and dept_cat = 'W'); SELECT ENAME (高效) select ename from dept d, emp e where e.dept_no = d.dept_no and dept_cat = 'W';
4.使用連接查詢
