天天看點

MySQL 聯表查詢和子查詢

兩個集合X和Y的笛卡兒積(Cartesian product),又稱直積,表示為X × Y,是其第一個對象是X的成員而第二個對象是Y的一個成員的所有可能的有序對。

假設集合A={a,b},集合B={0,1,2},則兩個集合的笛卡爾積為{(a,0),(a,1),(a,2),(b,0),(b,1), (b,2)}。

摘自:http://www.keepmyway.com/index.php/161.html

MYSQL執行流程的簡單探讨.

周末糾結了一個關于mysql執行流程的問題,現在有點感悟,寫下這篇blog,以做記錄! 現在網絡上有很多文章,都極力推薦在mysql的多表查詢中使用聯表式,而反對子查詢式.但大多文章都是隻說其然,而不說其是以然.

說到mysql的執行,就不得不說它的執行流程.而它的執行流程又分為标準執行流程和優化後的執行流程.

标準流程 标準流程是SQL執行的标準流程,幾乎所有的SQL資料庫都是以這個流程作為基礎的.那麼在聯表的時候,他的流程是怎麼樣的呢? 這裡會帶入兩個專業的名詞,笛卡爾積,虛拟表(Virtual Table 簡稱VT); 笛卡爾積這個說明的篇幅太長,大家可以先google一下,這裡就不說明了,而且一般有學過集合的同學,都知道這麼一個東西 VT就是虛拟的表,在mysql處理某個問題的時候,它需要一個容器存放内容,那麼這個容器就是VT.

以下是标準流程的舉例說明 SELECT * FROM T1 INNER JOIN T2 ON T1.id = T2.t1_id WHERE T1.name = ‘name’ LIMIT 5;

這是一個很常見的SQL語句.那它在标準流程中是怎麼執行的呢? 1.T1和T2進行笛卡爾積的計算,形成以個新的集合,放在一個VT内.我們稱這個VT為VT1; 2.對VT1進行ON條件的處理,找出VT1中符合T1.id = T2.t1_id條件的記錄,形成VT2; 3.對VT2進行WHERE字句處理,找出VT2中符合T1.name = ‘name’條件的記錄,形成VT3; 4.對VT3進行LIMIT字句處理,取出前5條資料,形成VT4; 5.傳回VT4;

這就是一個SQL的标準執行流程,由上面的流程可以看出,每兩表相聯的時候,都會先整理出一個笛卡爾集.這是非常消耗資源的.

這裡我們再看一個子查詢的處理過程. SELECT * FROM (SELECT * FROM T1 WHERE T1.name = ‘name’) as TMP INNER JOIN T2 ON TMP.id = T2.t1_id LIMIT 5;

如果按照标準的執行流程.這裡的處理流程是 1.對T1進行WHERE字句處理,得到一個臨時表TMP; 2.TMP和T2進行笛卡爾積的計算,形成以個新的集合,形成VT1; 3.對VT1進行ON條件的處理,找出VT1中符合T1.id = T2.t1_id條件的記錄,形成VT2; 4.對VT2進行WHERE字句處理,找出VT2中符合T1.name = ‘name’條件的記錄,形成VT3; 5.對VT3進行LIMIT字句處理,取出前5條資料,形成VT4; 6.傳回VT4;

對比之下,子查詢比INNER JOIN查詢多了一步的操作,就是先執行WHERE字句,過濾一遍T1,形成一個臨時表.這樣,使用TMP表和T2進行笛卡爾積計算的時候,因為TMP的資料比T1減少了很多,是以大大地提高了兩表連接配接的效率.雖然說因為子查詢而形成一個臨時表, 增加了開銷,但是卻能很大程度地減少笛卡爾積的體積,這個犧牲是可接受的.

如果是這樣的執行流程,子查詢肯定會比INNER JOIN快.那為什麼那麼多人推薦INNER JOIN呢?終究其原因就是,MYSQL優化器. 在MYSQL的語句執行之前,都會經過優化器,優化器對SQL進行一系列的處理,程式設計它自己認為效率最高的方式(但也有失誤的時候),然後再執行;

優化流程 以下是同一語句,經過MYSQL優化器處理之後的簡述.MYSQL優化器做的事很多,這裡隻是簡述. SELECT * FROM T1 INNER JOIN T2 ON T1.id = T2.t1_id WHERE T1.name = ‘name’ LIMIT 5;

1.發現T1是主表,而且WHERE字句中使用的是T1中的name字段作為條件,是以優先排除T1.name != ‘name’的記錄.形成VT1 2.TMP和T2進行笛卡爾積的計算,形成以個新的集合,形成VT2; 3.對VT2進行ON條件的處理,找出VT1中符合T1.id = T2.t1_id條件的記錄,形成VT3; 4.對VT3進行WHERE字句處理,找出VT2中符合T1.name = ‘name’條件的記錄,形成VT4; 5.對VT4進行LIMIT字句處理,取出前5條資料,形成VT5; 6.傳回VT5;

優化器自行優先執行了WEHRE字句的内容,不用通過子查詢來排除記錄,這樣既可以減少笛卡爾積的體積,同時也不會因為子查詢而産生了一個臨時表. 故得出,如果可以盡量使用聯表查詢的結論

題外拓展 很多時候,你自己認為的主表,并不是真正的主表.例如 SELECT * FROM T1 INNER JOIN T2 ON T1.id = T2.t1_id WHERE T2.name = ‘name’ LIMIT 5;

這條SQL中,用T2表中的name作為條件來查詢,當優化器察覺到這個問題的時候,它就會選擇T2作為主表,然後處理WHERE子句之後,再對T1進行聯接 雖然出來的結果是一樣的,但是他們的處理過程卻不一定是你所想象的 當然,這個還跟WEHRE子句中所用到到的索引有關系,總之優化器會選擇它認為最優的辦法來執行.但是,優化器認為是最優的,事實上并不一定是,是以我們要知道它的執行流程和規律,讓它在優化的時候,符合我們所想得.L

1、 mysql> SELECT t2.`RoomID`,t3.FloorID,t3.BuildingID FROM `bii_RoomUser` AS t1     -> LEFT JOIN `bii_Room` AS t2 ON(t2.RoomID = t1.RoomID)     -> LEFT JOIN `bii_Floor` AS t3 ON(t3.FloorID = t2.FloorID)     -> WHERE t1.UserID IN(166); +----------+---------+------------+ | RoomID   | FloorID | BuildingID | +----------+---------+------------+ | 10000026 | 1000012 |     100005 | | 10000027 | 1000012 |     100005 | | 10000028 | 1000012 |     100005 | +----------+---------+------------+ 3 rows in set (0.00 sec)

2、 mysql> select * from bii_RoomUser; +------------+--------+----------+ | RoomUserID | UserID | RoomID   | +------------+--------+----------+ |          1 |    111 | 10000015 | |          2 |    112 | 10000000 | |          3 |    114 | 10000000 | |          4 |    115 | 10000000 | |          5 |    136 | 10000000 | |          6 |    136 | 10000001 | |          7 |    136 | 10000002 | |          8 |    136 | 10000003 | |          9 |    136 | 10000008 | |         10 |    136 | 10000009 | |         11 |    136 | 10000015 | |         12 |    136 | 10000016 | |         13 |    137 | 10000000 | |         14 |    137 | 10000001 | |         15 |    137 | 10000002 | |         16 |    137 | 10000003 | |         17 |    137 | 10000015 | |         18 |    137 | 10000016 | |         19 |    137 | 10000008 | |         20 |    137 | 10000009 | |         21 |    137 | 10000004 | |         22 |    137 | 10000005 | |         23 |    137 | 10000024 | |         24 |    137 | 10000025 | |         25 |    138 | 10000004 | |         26 |    138 | 10000005 | |         27 |    138 | 10000024 | |         28 |    138 | 10000000 | |         29 |    138 | 10000015 | |         30 |    137 | 10000005 | |         31 |    155 | 10000000 | |         32 |    155 | 10000001 | |         33 |    155 | 10000002 | |         34 |    155 | 10000003 | |         35 |    155 | 10000008 | |         36 |    155 | 10000009 | |         37 |    155 | 10000015 | |         38 |    155 | 10000016 | |         39 |    156 | 10000000 | |         40 |    156 | 10000001 | |         41 |    156 | 10000002 | |         42 |    155 | 10000003 | |         43 |    156 | 10000008 | |         44 |    156 | 10000009 | |         45 |    156 | 10000015 | |         46 |    156 | 10000016 | |         47 |    157 | 10000000 | |         48 |    157 | 10000001 | |         49 |    157 | 10000002 | |         50 |    157 | 10000003 | |         51 |    157 | 10000008 | |         52 |    157 | 10000009 | |         53 |    157 | 10000015 | |         54 |    157 | 10000016 | |         55 |    158 | 10000000 | |         56 |    158 | 10000001 | |         57 |    158 | 10000002 | |         58 |    158 | 10000003 | |         59 |    158 | 10000008 | |         60 |    158 | 10000009 | |         61 |    158 | 10000015 | |         62 |    158 | 10000016 | |         63 |    166 | 10000026 | |         64 |    166 | 10000027 | |         65 |    166 | 10000028 | |         66 |    170 | 10000000 | |         67 |    170 | 10000001 | |         68 |    170 | 10000002 | |         69 |    170 | 10000003 | |         70 |    170 | 10000008 | |         71 |    170 | 10000009 | |         72 |    170 | 10000015 | |         73 |    170 | 10000016 | +------------+--------+----------+ 73 rows in set (0.00 sec)

3、 mysql> select * from bii_Room; +----------+---------------+-------------------------------------------------------------------------+---------+----------+--------------------------------------------+---------+ | RoomID   | RoomName      | Location                                                                | FloorID | IsPublic | Pic                                        | Point   | +----------+---------------+-------------------------------------------------------------------------+---------+----------+--------------------------------------------+---------+ | 10000000 | 大會議室      | 90,19,120,13,144,9,172,5,204,6,219,8,219,104,90,104                     | 1000000 |        0 | userfile/image/room/yicenghuiyishi.png     | 144,52  | | 10000001 | 男衛生間      | 260,13,285,23,306,33,306,103,260,103                                    | 1000000 |        0 | userfile/image/room/yicengnanwei.png       | 274,53  | | 10000002 | 女衛生間      | 304,33,330,49,354,75,366,103,304,103                                    | 1000000 |        0 | userfile/image/room/yicengnvwei.png        | 321,63  | | 10000003 | 公共區域      | 4,103,366,103,366,149,4,149                                             | 1000000 |        1 | userfile/image/room/yicengdating.png       | 193,115 | | 10000004 | 接待室        | 87,147,186,147,186,239,150,235,120,231,87,220                           | 1000000 |        0 | userfile/image/room/yicengjiedaishi.png    | 129,171 | | 10000005 | 大會議室      | 216,149,362,149,354,169,336,187,312,207,282,221,252,229,235,235,216,237 | 1000001 |        0 | userfile/image/room/ercenghuiyishi.png     | 251,174 | | 10000006 | 男衛生間      | 259,15,281,24,202,32,202,104,259,104                                    | 1000001 |        0 | userfile/image/room/ercengnanwei.png       | 273,50  | | 10000007 | 女衛生間      | 302,32,327,48,344,66,356,84,365,102,302,102                             | 1000001 |        0 | userfile/image/room/ercengnvwei.png        | 317,68  | | 10000008 | 辦公區        | 72,32,95,20,131,9,161,5,185,3,215,6,233,8,233,61,72,61                  | 1000001 |        0 | userfile/image/room/ercengbanggongqu.png   | 149,24  | | 10000009 | 第二洽談室    | 72,61,173,61,173,126,72,126                                             | 1000001 |        0 | userfile/image/room/ercengdierqiatang.png  | 113,84  | | 10000010 | 男衛生間      | 259,15,283,23,304,34,304,103,259,103                                    | 1000002 |        0 | userfile/image/room/sancengnanwei.png      | 271,55  | | 10000011 | 女衛生間      | 304,34,324,45,340,61,355,79,366,103,304,103                             | 1000002 |        0 | userfile/image/room/sancengnvwei.png       | 317,67  | | 10000015 | A-101機房     | 365,81,422,81,422,113,365,113                                           | 1000008 |        0 | userfile/image/room/jifang.png             | 380,82  | | 10000016 | A座大廳       | 163,59,243,59,243,113,163,113                                           | 1000008 |        0 | userfile/image/room/dating.png             | 191,73  | | 10000024 | 第三洽談室    | 1,126,11,94,17,76,23,57,56,38,92,30,72,26                               | 1000001 |        0 | userfile/image/room/ercengdisanqiatang.png | 32,84   | | 10000025 | 休息室        | 87,165,186,165,186,237,161,237,137,234,113,228,87,219                   | 1000001 |        0 | userfile/image/room/ercengxiuxishi.png     | 125,184 | | 10000026 | NEC辦公區西片 | 0,0,142,0,142,400,0,400                                                 | 1000012 |        0 | userfile/image/room/NECxi.png              | 59,110  | | 10000027 | NEC辦公區中片 | 142,0,290,0,290,400,142,400                                             | 1000012 |        0 | userfile/image/room/NECzhong.png           | 196,110 | | 10000028 | NEC辦公區東片 | 290,0,425,0,425,400,290,400                                             | 1000012 |        0 | userfile/image/room/NECdong.png            | 345,110 | +----------+---------------+-------------------------------------------------------------------------+---------+----------+--------------------------------------------+---------+ 19 rows in set (0.00 sec)

4、 mysql> select * from bii_Floor; +---------+-------+-----------+----------+------------+-------------------------------------+ | FloorID | Floor | FloorName | Location | BuildingID | Pic                                 | +---------+-------+-----------+----------+------------+-------------------------------------+ | 1000000 |     1 | 1         |          |     100002 | userfile/image/floor/C1.png         | | 1000001 |     2 | 2         |          |     100002 | userfile/image/floor/C2.png         | | 1000002 |     3 | 3         |          |     100002 | userfile/image/floor/C3.png         | | 1000003 |     0 | B1        |          |     100002 |                                     | | 1000004 |     1 | 1         |          |     100001 |                                     | | 1000005 |     2 | 2         |          |     100001 |                                     | | 1000006 |     3 | 3         |          |     100001 |                                     | | 1000007 |    -1 | B1        |          |     100001 |                                     | | 1000008 |     1 | 1         |          |     100000 | userfile/image/floor/A1.png         | | 1000009 |     2 | 2         |          |     100000 |                                     | | 1000010 |     3 | 3         |          |     100000 |                                     | | 1000011 |    -1 | B1        |          |     100000 |                                     | | 1000012 |    11 | 11        |          |     100005 | userfile/image/floor/NEClouceng.png | +---------+-------+-----------+----------+------------+-------------------------------------+ 13 rows in set (0.00 sec)

繼續閱讀