天天看點

mysql關鍵字之exists和in原理剖析

In關鍵字原理:

SELECT * FROM

user

WHERE id in (SELECT user_id FROM

product

)

in()語句隻會執行一次,它查出

product

表中的所有user_id字段并且緩存起來,之後,檢查

user

表的id是否和

product

表中的user_id相當,如果相等則加入結果期,直到周遊完

user

的所有記錄。

原理:笛卡爾積,周遊外表次數*内表次數

in的查詢過程類似于以下過程:

$result = [];
$users = "SELECT * FROM `user`";
$products = "SELECT user_id FROM `product`";
for($i = 0;$i < $users.length;$i++){
    for($j = 0;$j < $products .length;$j++){
        // 此過程為記憶體操作,不涉及資料庫查詢。
        if($users[$i].id == $products[$j].user_id){
            $result[] = $users[$i];
            break;
        }
    }
}
           

exists關鍵字原理

SELECT * FROM

user

WHERE exists (SELECT * FROM

product

WHERE user.id = product.user_id)

exists語句會執行user.length次,它并不會去緩存exists的結果集,因為這個結果集并不重要,你隻需要傳回真假即可。

原理:外表次數*内表記錄查詢sql

exists的查詢過程類似于以下過程:

$result = [];
$users = "SELECT * FROM `user`";
for($i=0;$i<$users.length;$i++){
    if(exists($users[$i].id)){// 執行SELECT * FROM `product` WHERE user.id = product.user_id
        $result[] = $users[$i];
    }
}
           

當product表比user表大很多的時候,使用exists是再恰當不過了,它沒有那麼多周遊操作,隻需要再執行一次查詢就行。

但是:user表有10000條記錄,product表有100條記錄,那麼exists()還是執行10000次,還不如使用in()周遊10000*100次,因為

in()是在記憶體裡周遊,而exists()需要查詢資料庫

,我們都知道查詢資料庫所消耗的性能更高,而記憶體比較很快.

結論:exist适合子表比父表資料大的情況,in則相反。使用時,需要正确評估父子表的資料預期增長情況做合适的選擇。

繼續閱讀