MySQL的Join查詢詳解

2021-10-10 11:18:40 字數 2360 閱讀 7570

create

table

`t1`

(`id`

int(11)

notnull

,`a`

int(11)

default

null

,`b`

int(11)

default

null

,primary

key(

`id`),

key`a`

(`a`))

engine

=innodb

;

t1裡插入100條資料

create

table

`t2`

(`id`

int(11)

notnull

,`a`

int(11)

default

null

,`b`

int(11)

default

null

,primary

key(

`id`),

key`a`

(`a`))

engine

=innodb

;

t2裡插入1000調資料

//straight_join讓mysql使用固定的連線方式進行查詢

select

*from t1 straight_join t2 on

(t1.a=t2.a)

;

t1是驅動表,t2是被驅動表

這種查詢操作可以用上被驅動表t2上的索引,叫做 index nested-loop join。

對應流程如下:

複雜度: 驅動表t1做了全表掃瞄,共100行,被驅動表通過樹搜尋,由於構造的資料一一對應,所以也為掃瞄100行,共計掃瞄200行。

然後分析下如果只用單錶查詢,發現是查處表t1的所有資料,遍歷所有資料,每一行執行查詢sql,這樣看來多增加了很多次的互動,這樣看來還不如join的好

所以本質上還是可以使用join的。

在join執行中,驅動錶走全表掃瞄,被驅動錶走樹搜尋。

那麼假設驅動表的行數為n,被驅動表的行數為m,被驅動表搜尋一行資料的複雜度為2∗l

og2m

2*log_2m

2∗log2

​m驅動表的行數是n,所以整體複雜度為

n +n

∗2∗l

og2m

n+n*2*log_2m

n+n∗2∗

log2

​m整體來看,n對整體掃瞄行數的影響更大。

綜上:前提是可以使用被驅動表的索引

由於表 t2 的字段 b 上沒有索引,每次到 t2 去匹配的時候,就要做一次全表掃瞄。

select

*from t1 straight_join t2 on

(t1.a=t2.b)

;

按照之前的資料量計算,需要掃瞄100*1000=10萬行

mysql最終沒有採用這個方案,而採用了另外一種方案

當被驅動表上沒有索引,流程如下:

總體複雜度為

當join_buffer放不下的時候,就採用分段放的方式。

假設,驅動表的資料行數是 n,需要分 k 段才能完成演算法流程,被驅動表的資料行數是 m。

注意,這裡的 k 不是常數,n 越大 k 就會越大,因此把 k 表示為λ*n,顯然λ的取值範圍是 (0,1)。

所以,在這個演算法的執行過程中:

顯然,記憶體判斷次數是不受選擇哪個表作為驅動表影響的。而考慮到掃瞄行數,在 m 和 n 大小確定的情況下,n 小一些,整個算式的結果會更小。

所以讓小表當驅動表。

在 n+λnm 這個式子裡,λ才是影響掃瞄行數的關鍵因素,這個值越小越好。

什麼引數會影響 k 的大小呢?(也就是λ的大小)答案是 join_buffer_size。join_buffer_size 越大,一次可以放入的行越多,分成的段數也就越少,對被驅動表的全表掃瞄次數就越少。

這就是為什麼,你可能會看到一些建議告訴你,如果你的 join 語句很慢,就把 join_buffer_size 改大。

能不能使用 join 語句?

如果要使用 join,應該選擇大表做驅動表還是選擇小表做驅動表?

總是使用小表做驅動表

決定哪個表做驅動表的時候,應該是兩個表按照各自的條件過濾,過濾完成之後,計算參與 join 的各個欄位的總資料量,資料量小的那個表,就是「小表」,應該作為驅動表。

MySQL中JOIN查詢詳解

一般而言,如果要設計乙個小型資料庫 指 量少 但又要適應海量資料及訪問的效能需求,最有效的方法莫過於針對主要應用場景選擇乙個或幾個效能優異的核心演算法作為引擎,然後努力將一些非主要應用場景作為該演算法的特例或變種植入到引擎當中。mysql postgresql 等就是這麼做的。在 mysql 的 s...

mysql的join連線查詢

join 聯合查詢。查詢的結果左右連線。連成一張大表。場景 一張表裡面的資訊不能滿足我們的條件這時候可以把有關聯的表連線起來。方便查詢。別名 分為表別名和列別名。因為有些資料表的表名很長並且會用很多次所以我們可以給它起乙個簡單的別名,簡便而且 也少。列別名主要是有相同欄位時可以加以區分。例如需要從兩...

mysql多表查詢方法(join)

表a記錄如下 aid anum 1 a20050111 2 a20050112 3 a20050113 4 a20050114 5 a20050115 表b記錄如下 bid bname 1 2006032401 2 2006032402 3 2006032403 4 2006032404 8 200...