云開發(fā) 索引

2020-07-22 15:32 更新

數(shù)據(jù)庫的索引與書籍的索引/目錄類似,有了索引就不需要翻整本書,數(shù)據(jù)庫可以直接在索引中查找,在索引中找到條目之后,就可以直接跳轉(zhuǎn)到目標(biāo)文檔的位置,這就能使查找速度提高幾個數(shù)量級。不使用索引的查詢稱為全表掃描,也就是說服務(wù)器必須查找完一整本書才能找到查詢結(jié)果,對于大集合來說,應(yīng)該盡量避免全表掃描,否則效率非常低。建立索引是保證數(shù)據(jù)庫性能、保證小程序體驗的重要手段。我們應(yīng)為所有需要成為查詢條件的字段建立索引。

一、 索引的類型與管理

我們可以在云開發(fā)控制臺數(shù)據(jù)庫標(biāo)簽頁對每個集合的字段添加索引,設(shè)置索引的屬性為唯一或非唯一,排序方式為升序或降序,也能查看該索引所占的空間和命中次數(shù)。索引是一個文件,它是要占據(jù)物理空間的,因此我們可以留意不要過度索引浪費空間,而命中次數(shù)也可以用于判斷索引是否有效。

1、_id索引和_openid索引

云開發(fā)數(shù)據(jù)庫會給每個集合默認建立_id索引和_openid索引。_id索引在我們進行db.collection('集合名').doc("_id值")的請求時就會命中。而當(dāng)我們在where里添加_openid為查詢條件,就會命中_openid索引,在小程序端進行db.collection('集合名')查詢時,由于自帶默認條件_openid為用戶的openid,因此在小程序端查詢都會命中_openid索引。

2、單字段索引

單字段索引是最常見的索引,它不會自動創(chuàng)建。對需要作為查詢條件篩選的字段,我們可以創(chuàng)建單字段索引。如果需要對嵌套字段進行索引,那么可以通過 "點表示法" 用點連接起嵌套字段的名稱。比如我們需要對如下格式的記錄中的 color 字段進行索引時,可以用 style.color 表示。在設(shè)置單字段索引時,指定排序為升序或降序都可以,。

{
  "_id": '',
  "style": {
    "color": ''
  }
}

3、組合索引

組合索引即一個索引包含多個字段,組合索引在添加時要注意字段的順序,順序不同索引的效果也會不同。當(dāng)查詢條件使用的字段包含在索引定義的所有字段或前綴字段里時,會命中索引。

組合索引遵循最左前綴原則,比如在 A, B, C 三個字段定義的組合索引(A, B, C),那么查詢條件A,{A, B},{A, C},{A, B, C}索引都會有效,查詢條件B,C,{B, C}則不會命中索引。根據(jù)最左前綴原則,我們可以明白組合索引(A, B)和調(diào)換字段順序的(B, A)效果是不一樣的。當(dāng)定義組合索引為(A, B)時,索引會先按 A 字段排序再按 B 字段排序。因此當(dāng)組合索引設(shè)為 (A, B) 時,即使我們沒有單獨對字段 A 設(shè)立索引,但對字段 A 的查詢可以命中 (A, B) 索引。

定義索引時字段的排序方式也決定排序查詢是否有效,比如我們對字段 A 和 B 設(shè)置以下索引:(A: 升序,B: 降序),那么當(dāng)我們查詢需要對 A, B 進行排序時,可以指定排序結(jié)果為 A 升序、B 降序以及完全相反的排序A 降序、B 升序有效,而A升B升,A降B降都不會命中索引。

還有一些查詢條件,需要進行范圍查詢或者排序,那么范圍查詢和排序的字段就要盡量往后放,因為范圍查詢以后的字段索引是不能命中的。組合索引的好處已經(jīng)在上面有提到了,如果數(shù)據(jù)庫有a索引,現(xiàn)在b列也需要索引,那么直接建立(a,b)即可

4、索引的唯一性

創(chuàng)建索引時可以指定增加唯一性限制,具有唯一性限制的索引會要求被索引集合不能存在被索引字段值都相同的兩個記錄。需特別注意的是,假如記錄中不存在某個字段,則對索引字段來說其值默認為 null,如果索引有唯一性限制,則不允許存在兩個或以上的該字段為空 / 不存在該字段的記錄。

db.collection("china")
  .where({
    gdp: _.gt(3000),
    city_area:_.lt(10000),
    reg_pop:_.gt(6000)
  })
  .field({
    _id:false,
    city: true,
    city_area: true,
    gdp:true
  })
  .orderBy('gdp', 'desc')
  .orderBy('city_area', 'asc') 

由于有三個查詢條件,為你可以給三個查詢條件按照順序創(chuàng)建索引,由于這幾個值無法做到非唯一,且存在空值的可能(有些城市沒有數(shù)據(jù)),所以創(chuàng)建時選擇非唯一。

二、 索引的創(chuàng)建說明

1、索引的優(yōu)點和缺點

索引雖然能非常高效的提高查詢速度,同時卻會降低更新表的速度。實際上索引也是一張表,該表保存了主鍵與索引字段,并指向?qū)嶓w表的記錄,所以索引列也是要占用空間的。索引需要進行兩次查找,一次是查找索引條目,一次是根據(jù)索引指針去查找相應(yīng)的文檔,而全表查詢只需要進行一次查找。集合較大、文檔較大、選擇性查詢就比較適合用索引。

其實建索引的原理就是將磁盤I/O操作的最小化,不在磁盤中排序,而是在內(nèi)存中排好序,通過排序的規(guī)則去指定磁盤讀取就行,也不需要在磁盤上隨機讀取。

索引并非越多越好,一個表中如有大量的索引,不僅占用磁盤空間,而且會影響增刪改等語句的性能,因為當(dāng)表中的數(shù)據(jù)更改的同時,索引也會進行調(diào)整和更新。避免對經(jīng)常更新的表設(shè)計過多的索引,并且索引中的列盡可能要少,而對經(jīng)常用于查詢的字段應(yīng)該創(chuàng)建索引,但要避免添加不必要的字段。

為了減少索引的數(shù)量,可以建立組合索引,組合索引就是可以使用多個列一起建立一個索引。建立索引時要優(yōu)先在已經(jīng)存在的索引上擴展成組合索引,或者在已經(jīng)存在的組合索引上繼續(xù)添加字段。因為,索引越多,維護成本就越高,還會導(dǎo)致插入速度變慢等負面效應(yīng)。

2、索引創(chuàng)建的條件

哪些情況需要創(chuàng)建索引:

  • 頻繁作為查詢條件的字段一般都應(yīng)該創(chuàng)建索引;

  • 查詢有多個條件時,組合索引比單字段索引的性價比更高;

  • 查詢中排序的字段,排序字段若通過索引去訪問將大大提高排序速度,注意單字段索引和組合索引的排序規(guī)則

  • 查詢中統(tǒng)計或分組字段也應(yīng)該建立索引

哪些情況不需要創(chuàng)建索引:

  • 集中中的記錄太少或記錄內(nèi)的字段太少;

  • 經(jīng)常增刪改的集合或字段;索引提高了查詢速度,同時也就會降低更新表的速度,因為更新表時,不僅要保存數(shù)據(jù),還要保存一下索引文件;因為如果該集合寫多讀少 ,添加索引會影響寫入性能

  • where條件里用不到的字段就不要創(chuàng)建索引

  • 數(shù)據(jù)重復(fù)且發(fā)布比較均勻的的字段不適合建索引(唯一性太差的字段不適合建立索引),例如性別,真假值

  • 參與列計算的列不適合建索引

3、索引的空間與命中

在云開發(fā)控制臺每個集合都有相應(yīng)的索引管理,在這里除了可以創(chuàng)建索引外,還可以了解每個索引占據(jù)的空間以及判斷查詢時索引是否命中的命中數(shù)。每個索引建議創(chuàng)建的索引數(shù)不要超過5個,索引占據(jù)的空間

三、 索引的原則與注意事項

1、最好是使用唯一索引

當(dāng)唯一性是某種數(shù)據(jù)本身的特征時,指定唯一索引。使用唯一索引需能確保定義的列的數(shù)據(jù)完整性,以提高查詢速度

2、和簡單的字段為索引

Innodb 表的普通索引都會保存主鍵的鍵值,所以主鍵要盡可能選擇較短的數(shù)據(jù)類型,可以有效的減少索引的磁盤占用,提高索引的緩存效果。索引的太長首先會占用大量的磁盤空間,其次索引太長會使索引變得臃腫,導(dǎo)致索引查詢變慢。通過目錄查詢書籍指定的章節(jié)之所以快,就是因為索引足夠輕量,如果索引太長那么這個優(yōu)勢就不明顯了。而且索引里的數(shù)據(jù)和表里的數(shù)據(jù)本身就是冗余的,如果索引太長,那么磁盤空間浪費的就越多。

3、用區(qū)分度比較高的列建索引

具有多個重復(fù)值的字段,其索引效果最差。比如存放身份證的字段因為值都不同,很容易區(qū)分,索引效果比較好,而用來記錄性別的字段,因為只含有“男”,“女”,不管搜索哪個值,都會得出大約一半的值,這樣的索引對性能的提升不高。如果有幾個列都是唯一的,要選擇最常作為訪問條件的列作為索引的主鍵。簡單枚舉值的列不要建立索引。在條件表達式中經(jīng)常用到的不同值較多的列上建立索引,在不同值較少的列上不要建立索引,比如性別字段只有男和女,就沒必要建立索引。如果建立索引不但不會提高查詢效率,反而會嚴(yán)重降低更新速度。由于我們建立索引并想讓索引能達到最高性能,這個時候我們應(yīng)當(dāng)充分考慮該列是否適合建立索引,可以根據(jù)列的區(qū)分度來判斷,區(qū)分度太低的情況下可以不考慮建立索引,區(qū)分度越高效率越高。

4、索引的字段的值最好不要有空值

索引的字段最好不要有空值,有空值的字段建立索引時要選擇非唯一性。唯一性的索引是不允許有空值的。

5、索引的字段最好不要參與計算

索引列不能參與計算,保持列“干凈”;索引列參與計算;應(yīng)盡量避免在 where 子句中對字段進行表達式操作

6、查詢盡量都走在索引上

保證索引包含的字段獨立在查詢語句中,不能是在表達式中,當(dāng)查詢的列都在索引的字段中時,查詢的效率更高,所以應(yīng)該盡量避免使用 select *,需要哪些字段,就只查哪些字段。在索引基數(shù)高的地方建立索引(比如郵箱,用戶名,而不是性別)

7、避免重復(fù)索引和冗余索引

重復(fù)索引:在同一列或者相同順序的幾個列建立了多個索引,成為重復(fù)索引,沒有任何意義,刪掉 冗余索引:兩個或多個索引所覆蓋的列有重疊,比如對于列m,n ,加索引index m(m),indexmn(m,n),稱為冗余索引。

8、使用索引獲取有序數(shù)據(jù)

索引本身是有序的,利用有序索引獲取有序數(shù)據(jù)(Using Index)。使用索引來優(yōu)化或者避免排序排序的字段上加入索引,可以提高速度。在頻繁排序或分組(即group by或order by操作)的列上建立索引,如果待排序的列有多個,可以在這些列上建立組合索引

9、組合索引遵循最左前綴原則

建立組合索引,要同時考慮列查詢的頻率和列的區(qū)分度,區(qū)分度大的優(yōu)先放在前面。比如一張全球人口的用戶表,該表有性別,國籍,年齡等字段。那么一般情況下國籍的區(qū)分度就要比性別的區(qū)分度更高,比如滿足中國人這個條件的要比滿足男人這個條件的人要更少。因此建組合索引時國籍優(yōu)先考慮放在性別的前面。

10、索引碎片與維護

在數(shù)據(jù)表長期的更改過程中,索引文件和數(shù)據(jù)文件都會產(chǎn)生空洞,形成碎片。修復(fù)表的過程十分耗費資源,可以用比較長的周期修復(fù)表。

11、注意索引的唯一性和非唯一性

唯一索引一定要小心使用,它帶有唯一約束,由于前期需求不明等情況下,可能造成我們對于唯一列的誤判。

12、建議最好不要用隨機生成的_id做主鍵

最好是使用自增ID字段做索引的主鍵,而不要使用隨機的_id做主鍵,因為非遞增的主鍵會導(dǎo)致頻繁的頁分裂,從而降低了插入的效率。所以一般情況下,我們會在表中使用一個自增ID字段來代替_id(使用原子更新指令inc來做自增),用該字段來作表的主鍵。如果需要按照_id查詢時,查找就需要回表,查找的效率會低一點。如果表中只需要一個_id的唯一索引,那么就可以使用_id來做主鍵;如果不滿足這個條件就用自增ID做索引;

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號