###### tags: `Index研究`
# 重要觀念
### 不是索引越多越好
索引可以加快查詢速度,但注意它是以空間換取時間。
基本上它使用的資源如下 :
每個索引都會建立一顆 b+ 樹。
每次新增、更新資料時都會改變 b+ 樹。
所以當你索引越多時,你所需要的記憶體與維護索引的 cpu 運算就需要越多。
> mongo的話就是建立B樹
### 索引不是建了就會使用
在 mysql 的世界,不是建了索引,且下的 query 正常就會一定會使用。
例如有以下的索引
```sql=
table: user
field: name, sex
index: {sex}
```
然後執行下面的 sql :
```sql=
SELECT * FROM user WHERE sex = 0 ( 0 代表女生 )
```
那這時會不會用索引呢 ?
答案是不一定,如果大部份的值都是女生,那 mysql 會用全掃,如果大部份值為男生,那 mysql 會用索引。
> 在mongo資料庫中,索引的欄位佔超過50%以上也會降低索引的效能,所以被索引的欄位需慎選,越分散效能越好。
> 結果集在原集合中所佔的比例越大,查詢效率越慢。因為使用索引需要進行兩次查找:一次查找索引條目,一次根據索引指針去查找相應的文檔。而全表掃描只需要進行一次查詢。在最壞的情況,使用索引進行查找次數會是全表掃描的兩倍。效率會明顯比全表掃描低。
> 而相反在提取較小的子數據集時,索引就非常有效
> ex:查找100筆中的60筆,利用index查需要進行120次查詢(60次找到指針,60次根據指針去找相應文檔),而使用全表查詢只需100次
### 利用Explain分析索引性能

# 注意事項
### 連合索引的欄位順序
假設有一個連合索引如下,由三個欄位 a、b、c 組合而成,而事實上在使用時,可以將它想成有下以三種組合,當然這不代表他有存放三顆樹。
```
{a, b, c}
=
{a}
{a,b}
{a,b,c}
```
然後根據三序的組合,使用上有個準則。
>tip:有用到最左邊的欄位的才能使用連合索引
以上面連合索引範例為例,下面為使用的 sql 是否會用到索引的情境。
```sql=
SELECT * FROM Table WHERE a = ? ( good 索引 )
SELECT * FROM Table WHERE a = ? AND b = ? ( good 索引 )
SELECT * FROM Table WHERE b = ? AND a = ? ( good 索引 )
SELECT * FROM Table WHERE b = ? ( bad 全掃 )
SELECT * FROM Table WHERE c = ? ( bad 全掃 )
SELECT * FROM Table WHERE b = ? AND c = ? ( bad 全掃 )
```
### 儘可能使用索引的排序
首先有個重點要記得,如下圖使用『 年齡 』所建立的索引 :
索引本身就是有排序的

這也代表如果要進行排序,儘可能的直接使用它,而不要讓資料庫另外開空間,來排序它。
**索引欄位: { age }**
```sql=
SELECT * FROM user WHERE age <= 30 ORDER BY age; ( good 索引 )
SELECT * FROM user WHERE age <= 30 ORDER BY name; ( bad using filesort )
```
其中上述範例中 bad 的 filesort 就是代表 mysql 需要另外使用記憶體來排序,這可以在 explain 時看到。
那連合索引呢 ?
它也有排序。
連合索引是以最左邊的欄位排序
所以假設你有一個索引為 :
**{ age, name }**
那它預設就會以 age 來排序,如下圖所示。

{%hackmd theme-dark %}