1、語法
子查詢有in和exists兩種,哪種速度更快呢?主要取決於兩張表的大小關係。
select * from a where cc in (select cc from b);
select * from a where exists (select cc from b where b.cc=a.cc);
in會先查詢b,然後把查詢b的結果,做為輸入,再查詢a,當 a 記錄多時,可以很好的利用 a 的索引,時間複雜度是o(b*log a)。
exists會先查詢a,然後把查詢a的結果,做為輸入,再查詢b,當 b 記錄多時,可以很好的利用 b 的索引,時間複雜度是o(a*log b)。
2、下面來做個實驗
(1)先執行 source first.sql; 來建立 2 張資料表
drop table if exists `t_big`;
create table `t_big` (
`id` int(11) not null auto_increment,
`name` varchar(30) not null,
`phone` varchar(30) not null,
primary key (`id`),
key idx_name(`name`),
key idx_phone(`phone`)
) engine = innodb;
drop table if exists `t_small`;
create table `t_small` (
`id` int(11) not null auto_increment,
`name` varchar(30) not null,
`nickname` varchar(30) not null,
primary key (`id`),
key idx_name(`name`),
key idx_nickname(`nickname`)
) engine = innodb;
(2)執行如下 shell 指令碼bash rand.sh來生成隨機資料的 sql 插入語句的 second.sql 檔案,再執行 source second.sql; 來插入資料:
#!/bin/bash
small=50
big=500000
rm -f second.sql
for((i=0;i
doprintf "insert into \`t_big\` (\`name\`, \`phone\`) values ('zhang%d', '%08d');\n" $[$random%1000000] $[$random%100000000] >> second.sql
done
for((i=0;i
doprintf "insert into \`t_small\` (\`name\`, \`nickname\`) values ('zhang%d', '%s');\n" $[$random%1000000] $(tr -dc "a-z"> second.sql
done
echo "create second.sql success!"
(3)此時大表 t_big 的記錄數量多,小表 t_small 的記錄少,可以看到使用 exists比 in 慢很多。
mysql> set profiling = 1;
select * from t_big where `name` in (select `name` from t_small);
mysql> show profiles;
| query_id | duration | query |
| 1 | 0.01406125 | select * from t_big where `name` in (select `name` from t_small) |
| query_id | duration | query |
| 1 | 1.65336600 | select * from t_big where exists (select `name` from t_small where t_big.name=t_small.name) |
(4)再做乙個相反的實驗讓兩個表的位置互換一下,可以看到 exists 比 in 快。
| query_id | duration | query |
| 1 | 0.00277950 | select * from t_small where `name` in (select `name` from t_big) |
| query_id | duration | query |
| 1 | 0.00050700 | select * from t_small where exists (select `name` from t_big where t_small.name=t_big.name) |
3、結論
當 a > b,用 in:
select * from a where cc in (select cc from b);
當 a < b,用 exists:
select * from a where exists (select cc from b where b.cc=a.cc);
mysql查詢效能優化 MySQL 查詢效能優化
在日常開發中,程式設計師寫的最多的除了bug之外,應該算是sql語句了。sql的質量影響了程式的響應速度,只有利用mysql的特性,才能讓mysql更有效的執行查詢sql,充分發揮mysql的優勢,並避開它的弱點。為什麼查詢速度會慢?在編寫sql之前,需要清楚一點 真正重要的是響應時間。如果我們把查...
mysql求和 子查詢 MySQL子查詢
到現在為止,我們已經表明,以select宣告是乙個簡單的查詢。該單個語句從單個資料庫表中檢索資料。sql還同意建立乙個子查詢。即巢狀在其他查詢的查詢。下列實施例給出巢狀查詢。一種表示訂單資訊儲存,包含訂單號,客戶id。訂購日期。例如以下所看到的 一張表示儲存訂單物品資訊,例如以下 另一張表儲存的是客...
mysql子查詢應用案例 MySQL子查詢
mysql子查詢 子查詢 sub query,查詢是在某個查詢結果之上進行的,一條select語句內部包含了另外一條select語句。分類子查詢有兩種分類方式,分別為 按按結果分類和位置分類。按結果分類,即根據子查詢得到的資料進行分類 理論上,任何乙個查詢結果都可以理解為乙個二維表 分別為 標量子查...