B 樹索引的使用

2021-09-21 09:00:00 字數 3531 閱讀 5343

並不是在所有的查詢條件下出現的列都需要新增索引。對於什麼時候新增b+樹索引,我的經驗是訪問表中很少一部分時,使用b+樹索引才有意義。對於性別字段,地區字段,型別字段,它們可取值的範圍很小,即低選著性。如:

select * from student where *** = 'm'

對於性別,可取值的範圍只有'm','f'。對上述sql語句得到的結果可能是該錶的50%的資料,這時新增b+樹索引時完全沒有必要的。相反,如果某個欄位的取值範圍很廣,幾乎沒有重複,即高選擇性,即此時使用b+樹索引時做合適的,例如姓名字段,基本上在乙個應用中都不允許重名的出現。

因此,當訪問高選擇性欄位並從表中取出很少一部分時,對這個字段新增b+樹索引是非常有必要的。但是如果出現了訪問欄位是高選擇性的,但是取出的行資料占用表中大部分的資料時,這時mysql資料庫就不會使用b+樹索引了,我們先來看乙個例子:

mysql> show index from info\g;

*************************** 1. row ***************************

table: info

non_unique: 0

key_name: primary

seq_in_index: 1

column_name: id

collation: a

cardinality: 356639

sub_part: null

packed: null

null: 

index_type: btree

comment: 

index_comment: 

*************************** 2. row ***************************

table: info

non_unique: 1

key_name: index_link_family

seq_in_index: 1

column_name: link_family

collation: a

cardinality: 9385

sub_part: 255

packed: null

null: yes

index_type: btree

comment: 

index_comment: 

*************************** 3. row ***************************

table: info

non_unique: 1

key_name: index_date

seq_in_index: 1

column_name: date

collation: a

cardinality: 356639

sub_part: null

packed: null

null: 

index_type: btree

comment: 

index_comment: 

表info大約有50萬行資料。info表上的date欄位,該字段是日期型別,欄位上有乙個index_date的非唯一索引。我們來看下面兩條sql的執行:

mysql> explain  select * from info where date = '2006-07-26 15:56:01'\g;

*************************** 1. row ***************************

id: 1

select_type: ******

table: info

type: ref

possible_keys: index_date

key: index_date

key_len: 8

ref: const

rows: 2

extra: 

1 row in set (0.00 sec)

error: 

no query specified

可以看到使用了index_date這個索引,這也符合我們前面提到的高選擇性,選取表中很少行的原則。但是如果執行下面這條語句:

mysql> explain  select * from info where date > '2006-07-26 15:56:01'\g;

*************************** 1. row ***************************

id: 1

select_type: ******

table: info

type: all

possible_keys: index_date

key: null

key_len: null

ref: null

rows: 356639

extra: using where

1 row in set (0.00 sec)

可以看到possible_keys依然是index_date,但是實際優化器使用的索引key顯示的是null。為什麼?因為這不符合我們前面說的原則,雖然date這個欄位的值是高選擇性的,但是我們取出的行占用了表中很大一部分。

mysql>   select @a:=count(id) from info where date > '2006-07-26 15:56:01';

+---------------+

| @a:=count(id) |

+---------------+

|        452549 |

+---------------+

1 row in set (0.18 sec)

mysql> select @b:=count(id) from info ;

+---------------+

| @b:=count(id) |

+---------------+

|        452554 |

+---------------+

1 row in set (0.11 sec)

mysql> select @a/@b;

+--------+

| @a/@b  |

+--------+

| 1.0000 |

+--------+

1 row in set (0.00 sec)

可以看到我們將取出行的數大概是表的100%的行,因此優化器沒有選擇使用索引。mysql資料庫的優化器會通過explain的rows欄位預估查詢可能得到的行,如果大於某乙個值,則b+樹會選擇全表的掃瞄。至於這個值,根據我的經驗一般在20%。即當取出的資料量超過表中資料的20%,優化器就不會使用索引,而是進行全表的掃表。

但是預估的返回行數的值是不準確的,可以看到優化器判斷日期小於2006-07-26的行為356639,而實際的是452549 。

有時優化器的選擇並不完全是正確的,有時你更應該相信自己的判斷(可以通過force index(index_name)來執行判斷兩條語句執行的時間差別)。

索引之B樹 B 樹 B 樹 B 樹

原文索引之b樹 b 樹 b 樹 b 樹 b 樹即二叉搜尋樹 1.所有非葉子結點至多擁有兩個兒子 left 和right 2.所有結點儲存乙個關鍵字 3.非葉子結點的左指標指向小於其關鍵字的子樹,右指標指向大於其關鍵字的子樹 如 b樹的搜尋,從根結點開始,如果查詢的關鍵字與結點的關鍵字相等,那麼就命中...

B樹與B 樹索引

b 樹 資料庫結構使用樹的結構索引,從演算法邏輯上看,二叉查詢樹的查詢速度和比較次數都是最小的。資料庫的索引儲存在磁碟上,當資料量比較大的時候,索引的大小可能有幾個g 甚至更多。當我們利用索引查詢的時候,不可能把整個索引載入到記憶體,能做的只有逐一載入每乙個磁碟頁,磁碟頁對應索引樹的節點。當利用二叉...

B樹 B 樹及索引

b樹 每個節點都儲存key和data,所有節點組成這棵樹,並且葉子節點指標為null。b 樹 只有葉子節點儲存data,葉子節點包含了這棵樹的所有鍵值,葉子節點不儲存指標。後來在b 樹上加了順序訪問指標,也就是每個葉子節點增加乙個指向相鄰葉子節點的指標。可以像遍歷鍊錶一樣遍歷葉子節點。b 樹是資料庫...