欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MySQL子查詢?cè)淼纳钊敕治?/h1>
 更新時(shí)間:2022年01月29日 11:07:54   作者:360云計(jì)算  
子查詢指一個(gè)查詢語(yǔ)句嵌套在另一個(gè)查詢語(yǔ)句內(nèi)部的查詢,這個(gè)特性從 MySQL 4.1 開始引入,下面這篇文章主要介紹了MySQL子查詢?cè)淼南嚓P(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

01前言

子查詢,通俗解釋就是查詢語(yǔ)句中嵌套著另一個(gè)查詢語(yǔ)句。相信日常工作中接觸到 MySQL 的同學(xué)都了解或使用過(guò)子查詢,但是具體它是怎樣實(shí)現(xiàn)的呢? 查詢效率如何? 這些恐怕好多人就不太清楚了,下面咱們就圍繞這兩個(gè)問(wèn)題共同探索一下。

02準(zhǔn)備內(nèi)容

這里我們需要用到3個(gè)表,這3個(gè)表都有一個(gè)主鍵索引 id 和一個(gè)索引 a,字段 b 上無(wú)索引。存儲(chǔ)過(guò)程 idata() 往表 t1 里插入的是 100 行數(shù)據(jù),表 t2、t3 里插入了 1000 行數(shù)據(jù)。建表語(yǔ)句如下:

CREATE TABLE `t1` (
    `id` INT ( 11 ) NOT NULL,
    `t1_a` INT ( 11 ) DEFAULT NULL,
    `t1_b` INT ( 11 ) DEFAULT NULL,
PRIMARY KEY ( `id` ),
KEY `idx_a` ( `t1_a` )) ENGINE = INNODB;

CREATE TABLE `t2` (
    `id` INT ( 11 ) NOT NULL,
    `t2_a` INT ( 11 ) DEFAULT NULL,
    `t2_b` INT ( 11 ) DEFAULT NULL,
PRIMARY KEY ( `id` ),
KEY `idx_a` ( `t2_a` )) ENGINE = INNODB;

CREATE TABLE `t3` (
    `id` INT ( 11 ) NOT NULL,
    `t3_a` INT ( 11 ) DEFAULT NULL,
    `t3_b` INT ( 11 ) DEFAULT NULL,
PRIMARY KEY ( `id` ),
KEY `idx_a` ( `t3_a` )) ENGINE = INNODB;

-- 向t1添加100條數(shù)據(jù)
-- drop procedure idata;
delimiter ;;
create procedure idata()
begin
  declare i int;
  set i=1;
  while(i<=100)do
        insert into t1 values(i, i, i);
    set i=i+1;
  end while;
end;;
delimiter ;
call idata();

-- 向t2添加1000條數(shù)據(jù)
drop procedure idata;
delimiter ;;
create procedure idata()
begin
  declare i int;
  set i=101;
  while(i<=1100)do
        insert into t2 values(i, i, i);
    set i=i+1;
  end while;
end;;
delimiter ;
call idata();

-- 向t2添加1000條數(shù)據(jù),且t3_a列的值為倒敘
drop procedure idata;
delimiter ;;
create procedure idata()
begin
  declare i int;
  set i=101;
  while(i<=1100)do
        insert into t3 values(i, 1101-i, i);
    set i=i+1;
  end while;
end;;
delimiter ;
call idata();

03子查詢的語(yǔ)法形式和分類

3.1 語(yǔ)法形式

子查詢的語(yǔ)法規(guī)定,子查詢可以在一個(gè)外層查詢的各種位置出現(xiàn),這里我們只介紹常用的幾個(gè):

3.1.1  FROM子句中

SELECT m, n FROM (SELECT m2 + 1 AS m, n2 AS n FROM t2 WHERE m2 > 2) AS t;

這個(gè)例子中的子查詢是:(SELECT m2 + 1 AS m, n2 AS n FROM t2 WHERE m2 > 2),這個(gè)放在FROM子句中的子查詢相當(dāng)于一個(gè)表,但又和我們平常使用的表有點(diǎn)兒不一樣,這種由子查詢結(jié)果集組成的表稱之為派生表。

3.1.2 WHERE或IN子句中

如:SELECT * FROM t1 WHERE m1 = (SELECT MIN(m2) FROM t2);

       SELECT * FROM t1 WHERE m1 IN (SELECT m2 FROM t2);

其他的還有 SELECT 子句中,ORDER BY 子句中,GROUP BY 子句中,雖然語(yǔ)法支持,但沒(méi)啥意義,就不嘮叨這些情況了。

3.2 分類

3.2.1 按返回的結(jié)果集區(qū)分

標(biāo)量子查詢,只返回一個(gè)單一值的子查詢稱之為標(biāo)量子查詢,比如:

SELECT * FROM t1 WHERE m1 = (SELECT m1 FROM t1 LIMIT 1);

行子查詢,就是只返回一條記錄的子查詢,不過(guò)這條記錄需要包含多個(gè)列(只包含一個(gè)列就成了標(biāo)量子查詢了)。比如:SELECT * FROM t1 WHERE (m1, n1) = (SELECT m2, n2 FROM t2 LIMIT 1);

列子查詢,就是只返回一個(gè)列的數(shù)據(jù),不過(guò)這個(gè)列的數(shù)據(jù)需要包含多條記錄(只包含一條記錄就成了標(biāo)量子查詢了)。比如:SELECT * FROM t1 WHERE m1 IN (SELECT m2 FROM t2);

表子查詢,就是子查詢的結(jié)果既包含很多條記錄,又包含很多個(gè)列,比如:

SELECT * FROM t1 WHERE (m1, n1) IN (SELECT m2, n2 FROM t2);

其中的 (SELECT m2, n2 FROM t2) 就是一個(gè)表子查詢,這里需要和行子查詢對(duì)比一下,行子查詢中我們用了 LIMIT 1 來(lái)保證子查詢的結(jié)果只有一條記錄。

3.2.2 按與外層查詢關(guān)系來(lái)區(qū)分

不相關(guān)子查詢,就是子查詢可以單獨(dú)運(yùn)行出結(jié)果,而不依賴于外層查詢的值,我們就可以把這個(gè)子查詢稱之為不相關(guān)子查詢。
相關(guān)子查詢,就是需要依賴于外層查詢的值的子查詢稱之為相關(guān)子查詢。比如:SELECT * FROM t1 WHERE m1 IN (SELECT m2 FROM t2 WHERE n1 = n2);

04子查詢?cè)贛ySQL中是怎么執(zhí)行的

4.1 標(biāo)量子查詢、行子查詢的執(zhí)行方式

4.1.1 不相關(guān)子查詢

如下邊這個(gè)查詢語(yǔ)句:

mysql root@localhost:test> explain select * from t1 where t1_a = (select t2_a from t2 limit 1);
+----+-------------+-------+-------+---------------+-------+---------+--------+------+-------------+
| id | select_type | table | type  | possible_keys | key   | key_len | ref    | rows | Extra       |
+----+-------------+-------+-------+---------------+-------+---------+--------+------+-------------+
| 1  | PRIMARY     | t1    | ref   | idx_a         | idx_a | 5       | const  | 1    | Using where |
| 2  | SUBQUERY    | t2    | index | <null>        | idx_a | 5       | <null> | 1000 | Using index |
+----+-------------+-------+-------+---------------+-------+---------+--------+------+-------------+

它的執(zhí)行方式:

先單獨(dú)執(zhí)行 (select t2_a from t2 limit 1) 這個(gè)子查詢。

然后在將上一步子查詢得到的結(jié)果當(dāng)作外層查詢的參數(shù)再執(zhí)行外層查詢 select * from t1 where t1_a = ...。

也就是說(shuō),對(duì)于包含不相關(guān)的標(biāo)量子查詢或者行子查詢的查詢語(yǔ)句來(lái)說(shuō),MySQL 會(huì)分別獨(dú)立的執(zhí)行外層查詢和子查詢,就當(dāng)作兩個(gè)單表查詢就好了。

4.1.2 相關(guān)的子查詢

比如下邊這個(gè)查詢:

mysql root@localhost:test> explain select * from t1 where t1_a = (select t2_a from t2 where t1.t1_b=t2.t2_b  limit 1);
+----+--------------------+-------+------+---------------+--------+---------+--------+------+-------------+
| id | select_type        | table | type | possible_keys | key    | key_len | ref    | rows | Extra       |
+----+--------------------+-------+------+---------------+--------+---------+--------+------+-------------+
| 1  | PRIMARY            | t1    | ALL  | <null>        | <null> | <null>  | <null> | 100  | Using where |
| 2  | DEPENDENT SUBQUERY | t2    | ALL  | <null>        | <null> | <null>  | <null> | 1000 | Using where |
+----+--------------------+-------+------+---------------+--------+---------+--------+------+-------------+

它的執(zhí)行方式就是這樣的:

先從外層查詢中獲取一條記錄,本例中也就是先從 t1 表中獲取一條記錄。

然后從上一步驟中獲取的那條記錄中找出子查詢中涉及到的值,就是 t1 表中找出 t1.t1_b 列的值,然后執(zhí)行子查詢。

最后根據(jù)子查詢的查詢結(jié)果來(lái)檢測(cè)外層查詢 WHERE 子句的條件是否成立,如果成立,就把外層查詢的那條記錄加入到結(jié)果集,否則就丟棄。

然后重復(fù)以上步驟,直到 t1 中的記錄全部匹配完。

4.2 IN子查詢

4.2.1 物化

如果子查詢的結(jié)果集中的記錄條數(shù)很少,那么把子查詢和外層查詢分別看成兩個(gè)單獨(dú)的單表查詢效率還是蠻高的,但是如果單獨(dú)執(zhí)行子查詢后的結(jié)果集太多的話,就會(huì)導(dǎo)致這些問(wèn)題:

結(jié)果集太多,可能內(nèi)存中都放不下~

對(duì)于外層查詢來(lái)說(shuō),如果子查詢的結(jié)果集太多,那就意味著 IN 子句中的參數(shù)特別多,這就導(dǎo)致:

1)無(wú)法有效的使用索引,只能對(duì)外層查詢進(jìn)行全表掃描。

2)在對(duì)外層查詢執(zhí)行全表掃描時(shí),由于 IN 子句中的參數(shù)太多,這會(huì)導(dǎo)致檢測(cè)一條記錄是否符合和 IN 子句中的參數(shù)匹配花費(fèi)的時(shí)間太長(zhǎng)。

于是就有:不直接將不相關(guān)子查詢的結(jié)果集當(dāng)作外層查詢的參數(shù),而是將該結(jié)果集寫入一個(gè)臨時(shí)表里。寫入臨時(shí)表的過(guò)程是這樣的:

該臨時(shí)表的列就是子查詢結(jié)果集中的列。

寫入臨時(shí)表的記錄會(huì)被去重,讓臨時(shí)表變得更小,更省地方。

一般情況下子查詢結(jié)果集不大時(shí),就會(huì)為它建立基于內(nèi)存的使用 Memory 存儲(chǔ)引擎的臨時(shí)表,而且會(huì)為該表建立哈希索引。

如果子查詢的結(jié)果集非常大,超過(guò)了系統(tǒng)變量 tmp_table_size或者 max_heap_table_size,臨時(shí)表會(huì)轉(zhuǎn)而使用基于磁盤的存儲(chǔ)引擎來(lái)保存結(jié)果集中的記錄,索引類型也對(duì)應(yīng)轉(zhuǎn)變?yōu)?B+ 樹索引。

這個(gè)將子查詢結(jié)果集中的記錄保存到臨時(shí)表的過(guò)程稱之為物化(Materialize)。為了方便起見,我們就把那個(gè)存儲(chǔ)子查詢結(jié)果集的臨時(shí)表稱之為物化表。正因?yàn)槲锘碇械挠涗浂冀⒘怂饕ɑ趦?nèi)存的物化表有哈希索引,基于磁盤的有 B+ 樹索引),通過(guò)索引執(zhí)行IN語(yǔ)句判斷某個(gè)操作數(shù)在不在子查詢結(jié)果集中變得非常快,從而提升了子查詢語(yǔ)句的性能。

mysql root@localhost:test> explain select * from t3 where t3_a in (select t2_a from t2);
+----+--------------+-------------+--------+---------------+------------+---------+--------------+------+-------------+
| id | select_type  | table       | type   | possible_keys | key        | key_len | ref          | rows | Extra       |
+----+--------------+-------------+--------+---------------+------------+---------+--------------+------+-------------+
| 1  | SIMPLE       | t3          | ALL    | idx_a         | <null>     | <null>  | <null>       | 1000 | Using where |
| 1  | SIMPLE       | <subquery2> | eq_ref | <auto_key>    | <auto_key> | 5       | test.t3.t3_a | 1    | <null>      |
| 2  | MATERIALIZED | t2          | index  | idx_a         | idx_a      | 5       | <null>       | 1000 | Using index |
+----+--------------+-------------+--------+---------------+------------+---------+--------------+------+-------------+

其實(shí)上邊的查詢就相當(dāng)于表 t3 和子查詢物化表進(jìn)行內(nèi)連接:

mysql root@localhost:test> explain select * from t3 left join t2 on t3.t3_a=t2.t2_a;
+----+-------------+-------+------+---------------+--------+---------+--------------+------+--------+
| id | select_type | table | type | possible_keys | key    | key_len | ref          | rows | Extra  |
+----+-------------+-------+------+---------------+--------+---------+--------------+------+--------+
| 1  | SIMPLE      | t3    | ALL  | <null>        | <null> | <null>  | <null>       | 1000 | <null> |
| 1  | SIMPLE      | t2    | ref  | idx_a         | idx_a  | 5       | test.t3.t3_a | 1    | <null> |
+----+-------------+-------+------+---------------+--------+---------+--------------+------+--------+

此時(shí) MySQL 查詢優(yōu)化器會(huì)通過(guò)運(yùn)算來(lái)選擇成本更低的方案來(lái)執(zhí)行查詢。

雖然,上面通過(guò)物化表的方式,將IN子查詢轉(zhuǎn)換成了聯(lián)接查詢,但還是會(huì)有建立臨時(shí)表的成本,能不能不進(jìn)行物化操作直接把子查詢轉(zhuǎn)換為連接呢?直接轉(zhuǎn)換肯定不行。
-- 這里我們先構(gòu)造了3條記錄,其實(shí)也是構(gòu)造不唯一的普通索引

+------+------+------+
| id   | t2_a | t2_b |
+------+------+------+
| 1100 | 1000 | 1000 |
| 1101 | 1000 | 1000 |
| 1102 | 1000 | 1000 |
+------+------+------+
-- 加限制條件where t2.id>=1100是為了減少要顯示的數(shù)據(jù)
mysql root@localhost:test> select * from t3 where t3_a in (select t2_a from t2 where t2.id>=1100);
+-----+------+------+
| id  | t3_a | t3_b |
+-----+------+------+
| 101 | 1000 | 101  |
+-----+------+------+
1 row in set
Time: 0.016s
mysql root@localhost:test> select * from t3 left join t2 on t3.t3_a=t2.t2_a where t2.id>=1100;
+-----+------+------+------+------+------+
| id  | t3_a | t3_b | id   | t2_a | t2_b |
+-----+------+------+------+------+------+
| 101 | 1000 | 101  | 1100 | 1000 | 1000 |
| 101 | 1000 | 101  | 1101 | 1000 | 1000 |
| 101 | 1000 | 101  | 1102 | 1000 | 1000 |
+-----+------+------+------+------+------+
3 rows in set
Time: 0.018s

所以說(shuō) IN 子查詢和表聯(lián)接之間并不完全等價(jià)。而我們需要的是另一種叫做半聯(lián)接 (semi-join) 的聯(lián)接方式 :對(duì)于 t3 表的某條記錄來(lái)說(shuō),我們只關(guān)心在 t2 表中是否存在與之匹配的記錄,而不關(guān)心具體有多少條記錄與之匹配,最終的結(jié)果集中也只保留 t3 表的記錄。

注意:semi-join 只是在 MySQL 內(nèi)部采用的一種執(zhí)行子查詢的方式,MySQL 并沒(méi)有提供面向用戶的 semi-join 語(yǔ)法。

4.2.2 半聯(lián)接的實(shí)現(xiàn):

  • Table pullout (子查詢中的表上拉)

當(dāng)子查詢的查詢列表處只有主鍵或者唯一索引列時(shí),可以直接把子查詢中的表上拉到外層查詢的 FROM 子句中,并把子查詢中的搜索條件合并到外層查詢的搜索條件中,比如這個(gè):

mysql root@localhost:test> select * from t3 where t3_a in (select t2_a from t2 where t2.id=999)
+-----+------+------+
| id  | t3_a | t3_b |
+-----+------+------+
| 102 | 999  | 102  |
+-----+------+------+
1 row in set
Time: 0.024s
mysql root@localhost:test> select * from t3 join t2 on t3.t3_a=t2.t2_a where t2.id=999;
+-----+------+------+-----+------+------+
| id  | t3_a | t3_b | id  | t2_a | t2_b |
+-----+------+------+-----+------+------+
| 102 | 999  | 102  | 999 | 999  | 999  |
+-----+------+------+-----+------+------+
1 row in set
Time: 0.028s
mysql root@localhost:test> explain select * from t3 where t3_a in (select t2_a from t2 where t2.id=999)
+----+-------------+-------+-------+---------------+---------+---------+-------+------+--------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref   | rows | Extra  |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+--------+
| 1  | SIMPLE      | t2    | const | PRIMARY,idx_a | PRIMARY | 4       | const | 1    | <null> |
| 1  | SIMPLE      | t3    | ref   | idx_a         | idx_a   | 5       | const | 1    | <null> |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+--------+
  • FirstMatch execution strategy (首次匹配)

FirstMatch 是一種最原始的半連接執(zhí)行方式,跟相關(guān)子查詢的執(zhí)行方式是一樣的,就是說(shuō)先取一條外層查詢的中的記錄,然后到子查詢的表中尋找符合匹配條件的記錄,如果能找到一條,則將該外層查詢的記錄放入最終的結(jié)果集并且停止查找更多匹配的記錄,如果找不到則把該外層查詢的記錄丟棄掉。然后再開始取下一條外層查詢中的記錄,重復(fù)上邊這個(gè)過(guò)程。

mysql root@localhost:test> explain select * from t3 where t3_a in (select t2_a from t2 where t2.t2_a=1000)
+----+-------------+-------+------+---------------+-------+---------+-------+------+-----------------------------+
| id | select_type | table | type | possible_keys | key   | key_len | ref   | rows | Extra                       |
+----+-------------+-------+------+---------------+-------+---------+-------+------+-----------------------------+
| 1  | SIMPLE      | t3    | ref  | idx_a         | idx_a | 5       | const | 1    | <null>                      |
| 1  | SIMPLE      | t2    | ref  | idx_a         | idx_a | 5       | const | 4    | Using index; FirstMatch(t3) |
+----+-------------+-------+------+---------------+-------+---------+-------+------+-----------------------------+
  • DuplicateWeedout execution strategy (重復(fù)值消除)

轉(zhuǎn)換為半連接查詢后,t3 表中的某條記錄可能在 t2 表中有多條匹配的記錄,所以該條記錄可能多次被添加到最后的結(jié)果集中,為了消除重復(fù),我們可以建立一個(gè)臨時(shí)表,并設(shè)置主鍵id,每當(dāng)某條 t3 表中的記錄要加入結(jié)果集時(shí),就首先把這條記錄的id值加入到這個(gè)臨時(shí)表里,如果添加成功,說(shuō)明之前這條 t2 表中的記錄并沒(méi)有加入最終的結(jié)果集,是一條需要的結(jié)果;如果添加失敗,說(shuō)明之前這條 s1 表中的記錄已經(jīng)加入過(guò)最終的結(jié)果集,直接把它丟棄。

  • LooseScan execution strategy (松散掃描)

這種雖然是掃描索引,但只取值相同的記錄的第一條去做匹配操作的方式稱之為松散掃描。

4.2.3 半聯(lián)接的適用條件

當(dāng)然,并不是所有包含IN子查詢的查詢語(yǔ)句都可以轉(zhuǎn)換為 semi-join,只有形如這樣的查詢才可以被轉(zhuǎn)換為 semi-join:

SELECT ... FROM outer_tables?
? ? WHERE expr IN (SELECT ... FROM inner_tables ...) AND ...

-- 或者這樣的形式也可以:

SELECT ... FROM outer_tables?
? ? WHERE (oe1, oe2, ...) IN (SELECT ie1, ie2, ... FROM inner_tables ...) AND ...

用文字總結(jié)一下,只有符合下邊這些條件的子查詢才可以被轉(zhuǎn)換為 semi-join:

  1. 該子查詢必須是和IN語(yǔ)句組成的布爾表達(dá)式,并且在外層查詢的 WHERE 或者 ON 子句中出現(xiàn)
  2. 外層查詢也可以有其他的搜索條件,只不過(guò)和 IN 子查詢的搜索條件必須使用AND 連接起來(lái)
  3. 該子查詢必須是一個(gè)單一的查詢,不能是由若干查詢由 UNION 連接起來(lái)的形式
  4. 該子查詢不能包含 GROUP BY 或者 HAVING 語(yǔ)句或者聚集函數(shù)

4.2.4 轉(zhuǎn)為 EXISTS 子查詢

不管子查詢是相關(guān)的還是不相關(guān)的,都可以把 IN 子查詢嘗試轉(zhuǎn)為 EXISTS子查詢。其實(shí)對(duì)于任意一個(gè) IN 子查詢來(lái)說(shuō),都可以被轉(zhuǎn)為 EXISTS 子查詢,通用的例子如下:

outer_expr IN (SELECT inner_expr FROM ... WHERE subquery_where)
-- 可以被轉(zhuǎn)換為:
EXISTS (SELECT inner_expr FROM ... WHERE subquery_where AND outer_expr=inner_expr)

當(dāng)然這個(gè)過(guò)程中有一些特殊情況,比如在 outer_expr 或者 inner_expr 值為 NULL 的情況下就比較特殊。因?yàn)橛?NULL 值作為操作數(shù)的表達(dá)式結(jié)果往往是 NULL,比方說(shuō):

mysql root@localhost:test> SELECT NULL IN (1, 2, 3);
+-------------------+
| NULL IN (1, 2, 3) |
+-------------------+
| <null>            |
+-------------------+
1 row in set

而 EXISTS 子查詢的結(jié)果肯定是 TRUE 或者 FASLE 。但是現(xiàn)實(shí)中我們大部分使用 IN 子查詢的場(chǎng)景是把它放在 WHERE 或者 ON 子句中,而 WHERE 或者 ON 子句是不區(qū)分 NULL 和 FALSE 的,比方說(shuō):

mysql root@localhost:test> SELECT 1 FROM s1 WHERE NULL;
+---+
| 1 |
+---+
0 rows in set
Time: 0.016s
mysql root@localhost:test> SELECT 1 FROM s1 WHERE FALSE;
+---+
| 1 |
+---+
0 rows in set
Time: 0.033s

所以只要我們的IN子查詢是放在 WHERE 或者 ON 子句中的,那么 IN ->  EXISTS 的轉(zhuǎn)換就是沒(méi)問(wèn)題的。說(shuō)了這么多,為啥要轉(zhuǎn)換呢?這是因?yàn)椴晦D(zhuǎn)換的話可能用不到索引,比方說(shuō)下邊這個(gè)查詢:

mysql root@localhost:test> explain select * from t3 where t3_a in (select t2_a from t2 where t2.t2_a>=999) or t3_b > 1000;
+----+-------------+-------+-------+---------------+--------+---------+--------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key    | key_len | ref    | rows | Extra                    |
+----+-------------+-------+-------+---------------+--------+---------+--------+------+--------------------------+
| 1  | PRIMARY     | t3    | ALL   | <null>        | <null> | <null>  | <null> | 1000 | Using where              |
| 2  | SUBQUERY    | t2    | range | idx_a         | idx_a  | 5       | <null> | 107  | Using where; Using index |
+----+-------------+-------+-------+---------------+--------+---------+--------+------+--------------------------+

但是將它轉(zhuǎn)為 EXISTS 子查詢后卻可以使用到索引:

mysql root@localhost:test> explain select * from t3 where exists (select 1 from t2 where t2.t2_a>=999 and t2.t2_a=t3.t3_a) or t3_b > 1000;
+----+--------------------+-------+------+---------------+--------+---------+--------------+------+--------------------------+
| id | select_type        | table | type | possible_keys | key    | key_len | ref          | rows | Extra                    |
+----+--------------------+-------+------+---------------+--------+---------+--------------+------+--------------------------+
| 1  | PRIMARY            | t3    | ALL  | <null>        | <null> | <null>  | <null>       | 1000 | Using where              |
| 2  | DEPENDENT SUBQUERY | t2    | ref  | idx_a         | idx_a  | 5       | test.t3.t3_a | 1    | Using where; Using index |
+----+--------------------+-------+------+---------------+--------+---------+--------------+------+--------------------------+

需要注意的是,如果 IN 子查詢不滿足轉(zhuǎn)換為 semi-join 的條件,又不能轉(zhuǎn)換為物化表或者轉(zhuǎn)換為物化表的成本太大,那么它就會(huì)被轉(zhuǎn)換為 EXISTS 查詢?;蛘咿D(zhuǎn)換為物化表的成本太大,那么它就會(huì)被轉(zhuǎn)換為 EXISTS 查詢。

05總結(jié)

1. 如果IN子查詢符合轉(zhuǎn)換為 semi-join 的條件,查詢優(yōu)化器會(huì)優(yōu)先把該子查詢轉(zhuǎn)換為 semi-join,然后再考慮下邊執(zhí)行半連接的策略中哪個(gè)成本最低,

1)Table pullout

2)DuplicateWeedout

3)LooseScan

4)FirstMatch

選擇成本最低的那種執(zhí)行策略來(lái)執(zhí)行子查詢。

2. 如果IN子查詢不符合轉(zhuǎn)換為 semi-join 的條件,那么查詢優(yōu)化器會(huì)從下邊兩種策略中找出一種成本更低的方式執(zhí)行子查詢:

1)先將子查詢物化之后再執(zhí)行查詢

2)執(zhí)行 IN to EXISTS 轉(zhuǎn)換

到此這篇關(guān)于MySQL子查詢?cè)淼奈恼戮徒榻B到這了,更多相關(guān)MySQL子查詢?cè)韮?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Ubuntu20下MySQL?8.0.28?安裝卸載方法圖文教程

    Ubuntu20下MySQL?8.0.28?安裝卸載方法圖文教程

    這篇文章主要為大家詳細(xì)介紹了Ubuntu20下MySQL?8.0.28?安裝卸載方法圖文教程,文中安裝步驟介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • MySQL表LEFT JOIN左連接與RIGHT JOIN右連接的實(shí)例教程

    MySQL表LEFT JOIN左連接與RIGHT JOIN右連接的實(shí)例教程

    這篇文章主要介紹了MySQL表LEFT JOIN左連接與RIGHT JOIN右連接的實(shí)例教程,表連接操作是MySQL入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-12-12
  • Navicat使用報(bào)2059錯(cuò)誤的兩種解決方案

    Navicat使用報(bào)2059錯(cuò)誤的兩種解決方案

    Navicat是一款流行的數(shù)據(jù)庫(kù)管理工具,而MySQL則是其中的一種數(shù)據(jù)庫(kù)軟件,下面這篇文章主要給大家介紹了關(guān)于Navicat使用報(bào)2059錯(cuò)誤的兩種解決方案,需要的朋友可以參考下
    2023-11-11
  • 一文掌握MySQL鎖表方法

    一文掌握MySQL鎖表方法

    在MySQL中,可以使用多種方法來(lái)鎖定表,這些方法取決于你的具體需求,比如是鎖定整個(gè)表還是行級(jí)鎖,本文給大家分享一些常用的MySQL鎖表方法,感興趣的朋友跟隨小編一起看看吧
    2024-02-02
  • mysql如何實(shí)現(xiàn)最大連接數(shù)

    mysql如何實(shí)現(xiàn)最大連接數(shù)

    云服務(wù)器同時(shí)最大連接數(shù),也就是說(shuō)可以有一千個(gè)用戶,那么mysql如何實(shí)現(xiàn)最大連接數(shù),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • MySQL group by和order by如何一起使用

    MySQL group by和order by如何一起使用

    這篇文章主要介紹了MySQL group by和order by如何一起使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10
  • MySQL優(yōu)化案例系列-mysql分頁(yè)優(yōu)化

    MySQL優(yōu)化案例系列-mysql分頁(yè)優(yōu)化

    這篇文章主要介紹了MySQL優(yōu)化案例系列-mysql分頁(yè)優(yōu)化,需要的朋友可以參考下
    2016-08-08
  • mysql 5.7.25 壓縮版安裝配置方法圖文教程

    mysql 5.7.25 壓縮版安裝配置方法圖文教程

    這篇文章主要為大家詳細(xì)介紹了mysql 5.7.25 壓縮版安裝配置方法圖文教程,文中安裝步驟介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • mysql簡(jiǎn)單實(shí)現(xiàn)查詢結(jié)果添加序列號(hào)的方法

    mysql簡(jiǎn)單實(shí)現(xiàn)查詢結(jié)果添加序列號(hào)的方法

    這篇文章主要介紹了mysql簡(jiǎn)單實(shí)現(xiàn)查詢結(jié)果添加序列號(hào)的方法,結(jié)合實(shí)例形式演示了2種查詢結(jié)果添加序列號(hào)的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2016-06-06
  • 分享CentOS下MySQL最新版本5.6.13源碼安裝過(guò)程

    分享CentOS下MySQL最新版本5.6.13源碼安裝過(guò)程

    這篇文章主要介紹了CentOS下安裝MySQL最新版本5.6.13過(guò)程分享,需要的朋友可以參考下
    2014-02-02

最新評(píng)論