MySQL:in、exists、like、find_in_set

堅持小表驅動大表的原則。

有人在爭exists查詢與in查詢的效率問題,這裏得說以下,不同的mysql版本,不同的業務,不同的數據,執行效率是不一定的,這裏涉及到了mysql優化器對sql語句的優化,子查詢的數據量問題等等。
網上還有人說mysql5.6版本對in查詢做了很好的優化,所以效率問題要看具體的場景,要看真實測試的數據來進行優化!

in

當B表的數據集必須小於A表的數據集時,in 優於 exists

-- 語法
SELECT * FROM A WHERE id IN (SELECT id FROM B);
SELECT * FROM A WHERE id NOT IN (11, '22', '2000-01-01');

-- in 列表項可以是數字、字符、日期、時間等類型,還能混合排列,無須和 column 類型保持一致
-- in 查詢相當於多個 or 條件疊加:一個 in 只能對一個字段進行範圍比對,如果要指定更多字段,可以使用 AND 或 OR 邏輯運算符
SELECT * FROM user WHERE uid IN(1,2) OR username IN('admin','manong');

1、先執行子查詢(in 包含的語句)。然後將A表查詢分爲n次(n表示在子查詢中返回的數據行數)。
SELECT * FROM A WHERE id=子查詢結果1;
SELECT * FROM A WHERE id=子查詢結果2;
......
2、Oracle中,in語句中可放的最大參數個數是1000個。mysql中,in語句中參數個數是不限制的。不過對整段sql語句的長度有了限制(max_allowed_packet 缺省值4M)。

exists

當A表的數據集小於B表的數據集時,exists 優於 in

SELECT * FROM A WHERE EXISTS(SELECT 1 FROM B WHERE B.id=A.id);

每次從A表中查出來一條數據,然後將結果裏的 id 放在 exists 查詢中執行。
子查詢查到返回布爾值 true,沒有查到返回布爾值 false。返回布爾值true則將該條數據保存下來,否則就捨棄掉。

MySQL NOT EXISTS優化的一個案例

like

like 廣泛的模糊匹配,字符串中沒有分隔符。

find_in_set(str, strlist)

find_in_set 精確匹配。
假如字符串str 在由N 子鏈組成的字符串列表strlist 中,則返回值的範圍在 1 到 N 之間。
一個字符串列表就是一個由一些被‘,’符號分開的子鏈組成的字符串。

SELECT * FROM A WHERE FIND_IN_SET(name, '張三,李四,王五');
SELECT * FROM A WHERE FIND_IN_SET(name, '11,22,33');

name 要查詢的字符串,strlist 字段名 參數以”,”分隔。
如果 name 不在 strlist 或 strlist 爲空字符串,則返回值爲 0 。如任意一個參數爲NULL,則返回值爲 NULL。這個函數在第一個參數包含一個逗號(‘,’)時將無法正常運行。

小結

1、如果待查詢的條件是常量那就使用 IN,是變量則使用 FIND_IN_SET。
2、如果使用 IN 和 FIND_IN_SET 都能滿足條件,則最好使用IN。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章