中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

MongoDB索引概念及使用詳解

發布時間:2020-06-14 22:31:12 來源:網絡 閱讀:2872 作者:zuzhou 欄目:MongoDB數據庫

索引,使用索引可快速訪問數據庫表中的特定信息。索引是對數據庫表中一列或多列的值進行排序的一種結構,例如 employee 表的姓名(name)列。如果要按姓查找特定職員,與必須搜索表中的所有行相比,索引會幫助您更快地獲得該信息。


索引的優點:

不需要做全表掃描,只需要掃描索引索引只存儲了這個表的數據的一小部分,這小部分可以幫我們實現快速查詢,因此掃描的時候只掃描這一小部分即可,如果將這小部分裝載入內存中的話,速度會更快

·大大減少了服務器需要掃描的數據量

·索引可以幫助服務器避免排序或使用臨時表

·索引可以將隨機I/O轉換為順序I/O


索引的缺點:

索引是保存了數據表上的一小部分數據,那么這些數據是需要額外存儲的,毫無疑問如果更新了表中的數據,那么響應的索引數據也要跟著更新,加速了查找操作,但是減少了寫入速度對查找的加速是否有用還是有待評估的,比如我們將一個表中的按年齡實現了索引創建(在年齡上創建了索引)平時大多數操作都是按照名字上去查找的,那么索引則無任何作用,所謂索引必須跟查找建完全匹配才有意義,但我們要知道大多數的查找未必只在有限字段上執行,也就意味著創建索引必須包含多個段,需要看索引是如何去生成的,對于多個條件可以將索引做為組合索引來查找,所以索引的設計是非常有技巧的

索引本身帶來的未必是優勢,如果一張表中索引非常的多的話,可能對于整個系統性能的影響是非常大的,如果一張表的本身非常小只有十幾行,創建索引反而會減慢速度的,因為全表掃描也未必用不了多長時間

但如果表非常大的話,索引則非常有用,如果數據量過大那么索引反而也未必有意義,比如一張表非常大,上T的數據,可以想象一下創建什么樣的索引才可以,所以只能將大表切割成小表,并且分布在不同的物理節點上,對mysql來說叫做分區;對mongodb來講叫shaerd


索引級別:

索引最高級別3星索引

1星:索引國能將相關的記錄放置在一起,大大降低了I/O

2星:索引中數據的存儲順序與查找標準中順序一致(只要設計良好即可)

3星:如果索引中包含查詢中所需要的全部數據(覆蓋索引)


索引的類別:

·順序索引
·散列索引

將索引映射至散列桶中,映射是通過散列函數進行的


評估索引標準:

1、訪問類型(如果做等值比較 散列比較好,如果做范圍查找,那么順序比較好

2、訪問時長(為完成一個訪問,基于索引類型訪問的時間可能不同)

3、插入時長(更新表的話索引本身可能會有很大代價,如果散列索引的話只不過重新執行以下算法即可,但是對于順序索引的話,有可能會移動索引列表后面的索引數據)

4、刪除時長

5、空間開銷


索引類型:

·順序索引:按照聚集索引存放的文件也被稱為索引順序文件,最常見的索引類型,一般來講被索引文件記錄,如果按照順序存放則為索引順序文件,否則為堆文件

·聚集索引:如果某記錄文件中的記錄順序是按照對應的搜索碼(鍵/key)的順序排序的話,被稱為主索引

·非聚集索引:搜索碼中的指定的次序與記錄中的記錄次序不一致


根據索引中是否為每個記錄響應的創建索引項:

·稠密索引 (每個搜索碼值都有一個對應的索引項

·稀疏索引 (并不是每個記錄都有索引項)

·多級索引 (索引指向索引,以此類推,最后的索引指向數據;

索引本身,主索引之外的索引被稱為輔助索引,而只有主索引才能使用稀疏索引,其他所有必需是稠密索引,而輔助索引必須是稠密索引

·B+樹索引:

·Balance Tree 平衡樹索引

·每個葉子節點,從葉子至根的距離是相同的,所以叫做平衡樹

·層次需要根據數據量來動態創建層次

·B+樹是一種順序索引



散列索引則:

通過散列函數,數據庫加載為一次I/O 指針加載數據為2次 I/O。

   I/O是占據時間比例是最大值的,索引散列索引的速度在做精確匹配的時候會更快,因為I/O次數要少的多的多,因此散列索引能夠讓我們避免訪問索引結構的。

散列索引的缺點:散列索引還有可能造成偏斜,長久以來可能發有的散列桶有的滿有的空 導致每個節點的負載參差不齊,如果散列函數做的不夠隨機就有可能造成偏斜的情況

所以散列函數需要做到以下幾點:

·分布式隨機

·分布式均勻

散列函數適用的場景:精確值匹配,比如做等值比較: = ,IN(), <=> 等


全文索引

默認情況下順序索引只能索引字段的前有限個字節,假如字段名是test,test是可以創建存儲文本量非常大,不可能將所有的數據全部存放在索引中,肯定只在其中抽取部分字節,所以查找標準肯定是最左前綴方式,不能包含整個字段,如果想實現全文匹配關鍵字匹配的話,這樣則只能使用全文索引(mysql中只有myisam引擎支持)(innodb的話則可以借助外界的索引工具來實現比如sphinx)

如果必須要實現全文索引,使用sphinx是個不錯的選擇


空間索引:

索引中的數據不能查找,必須使用空間索引函數來獲取相應查找結果


索引的特性:

·全值匹配:

簡單來講,匹配他的用戶名:Name="User12" ,匹配最左前綴

   Name LIKE"User1%"  

無效: Name LIKE"%User1%"


·匹配列前綴:與最左前綴一樣(Name LIKE"User1%"  無效: Name LIKE"%User1%") 假如組合索引創建了2個字段:Name,Age 從最左側開始則有效,那么Age > 80 這樣則沒有任何意義,因為查找條件一定必須從最左邊開始的,但是反過來則非常用有:(Age,Name)

匹配范圍值:精確匹配某一列并范圍匹配另外一列 比如name=12并age大于80


只訪問索引的查詢:

假設順序索引是3級,要找到對應的行數據,如果沒有使用覆蓋索引,那么需要幾次I/O:首先查找到根索引. 然后查找下一級索引,如果下一級索引在磁盤上,那么意味著將裝載數據塊,這為1次IO ,再一次索引則又消耗一次IO,再次裝載硬盤數據,則又一次I/O,如果事先根索引沒有被加載,那么至少需要4次I/O才會找到數據

主鍵,唯一鍵 都是順序索引,但是唯一不同的地方是:主鍵是不能重復 不能為空,唯一鍵可以重復可以為空


創建索引

> db.testcoll.find()

{ "_id" : ObjectId("531fbe8d020f14309ee1410a"), "Name" : "User1","Age" : 1, "Gender" : "M", "preferbook": [  "blue book",  "yellow book" ] }
{ "_id" : ObjectId("531fbe8d020f14309ee1410b"), "Name" : "User2","Age" : 2, "Gender" : "M", "preferbook": [  "blue book",  "yellow book" ] }
{ "_id" : ObjectId("531fbe8d020f14309ee1410c"), "Name" : "User3","Age" : 3, "Gender" : "M", "preferbook": [  "blue book",  "yellow book" ] }

如上所示,我們要在用戶字段名上創建索引,注意的是字段id默認就是索引,而且是主鍵索引,我們在主鍵索引之外創建索引都被稱為輔助索引 ,因為表內大多數都是根據用戶名來查找的,所以希望根據用戶名來查找索引:


使用命令ensureIndex 在Name字段上創建索引

> db.testcoll.ensureIndex({Name:1})

查看索引:

> db.testcoll.getIndexes()
[
    {
         "v" : 1,
         "key" : {
             "_id" : 1
         },
         "ns" :"testdb.testcoll",
         "name" :"_id_"
    },

#第二個索引是在name上創建,是我們自己指定的,如下所示:

    {
         "v" : 1,
         "key" : {
             "Name" : 1
         },
         "ns" :"testdb.testcoll",
         "name" :"Name_1"
    }

刪除索引:

可以使用dropIndex 將name字段的索引刪除

> db.testcoll.dropIndex({Name:1})
{ "nIndexesWas" : 2, "ok" : 1 }

再次查看其索引

> db.testcoll.getIndexes()
[
    {
         "v" : 1,
         "key" : {
             "_id" : 1
         },
         "ns" :"testdb.testcoll",
         "name" :"_id_"
    }
]

刪除coll所有的索引

> db.testcoll.dropIndex({Name:1})


同時也支持使用唯一索引,我們可以在name這個字段上創建唯一索引,也就意味著用戶名不得出現重復的名字

#唯一索引

> db.testcoll.ensureIndex({Name:1},{unique:true})

#稀疏索引

> db.testcoll.ensureIndex({Name:1},{sparse:true})


MongoDB中所支持的索引類型

對mongodb來講,索引可以創建在collection級別,也可以創建在sub-field中()子collection

完全可以根據自己的需求創建,那么索引可以將隨機IO轉換為順序IO

索引類型:

1、單鍵索引(創建在一個字段上的索引)

2、組合索引(上面提到了)

3、多鍵索引(一個文檔中某個字段的值可以是數組,如果創建在這么個字段上,一個字段上有多個值,則為多鍵索引,(一個值為一個數組))

4、空間索引(只能使用空間索引函數,與mysql一致)

5、文本索引(全文索引)

6、哈希索引


創建哈希索引的話,必須明確說明哈希的格式才可以,如下所示:

    >db.testcoll.ensureIndex({Name:"hashed"})

    > db.testcoll.dropIndex({Name:"hashed"})


顯示索引是否能用到:

顯示查詢語句是否能真正用到所創建的索引:

> db.testcoll.find({Name: "User19"}).explain()
{
    "cursor" : "BtreeCursor Name_1",
    "isMultiKey" : false,                    #
是否用到鍵
    "n" : 1,
    "nscannedObjects" : 1,
    "nscanned" : 1,                       #掃描了多少個記錄
    "nscannedObjectsAllPlans" : 1,
    "nscannedAllPlans" : 1,
    "scanAndOrder" : false,                #掃描后有沒有記錄
    "indexOnly" : false,                   #是否用到索引,是否僅在索引中
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 0,
    "indexBounds" : {
         "Name" : [
             [
                  "User19",
                  "User19"
             ]
         ]
    },
    "server" : "localhost:27017"
}


將索引刪除:

> db.testcoll.find({Name: "User19"}).explain()
{
    "cursor" : "BasicCursor",
    "isMultiKey" : false,
    "n" : 1,
    "nscannedObjects" : 99,             #
掃描的對象為全部,意為全表掃描
    "nscanned" : 99,
    "nscannedObjectsAllPlans" : 99,
    "nscannedAllPlans" : 99,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 0,
    "indexBounds" : {

    },
    "server" : "localhost:27017"
}

在查詢的時候可以用hint指定使用的索引

> db.testcoll.find({Name: "User19"}).hint({Name:1}).explain()


創建組合索引

> db.testcoll.ensureIndex({Name:1,Age:1},{uniqe:true})

> db.testcoll.getIndexes()
[
    {
         "v" : 1,
         "key" : {
             "_id" : 1
         },
         "ns" :"testdb.testcoll",
         "name" :"_id_"
    },
    {
         "v" : 1,
         "key" : {
             "Name" : 1,
             "Age" : 1
         },
         "ns" :"testdb.testcoll",
         "name" :"Name_1_Age_1",
         "uniqe" : true
    }
]

如果不指定則在name:1上查找索引。如下所示:

> db.testcoll.find({Name: "User19"}).explain()
{
    "cursor" : "BtreeCursor Name_1_Age_1",
    "isMultiKey" : false,
    "n" : 1,
    "nscannedObjects" : 1,
    "nscanned" : 1,
    "nscannedObjectsAllPlans" : 1,
    "nscannedAllPlans" : 1,
    "scanAndOrder" : false,
    "indexOnly" : false,
    "nYields" : 0,
    "nChunkSkips" : 0,
    "millis" : 0,
    "indexBounds" : {
         "Name" : [
             [
                  "User19",
                  "User19"
             ]
         ],
         "Age" : [
             [
                  {
                       "$minElement" : 1
                  },
                  {
                       "$maxElement" : 1
                  }
             ]
         ]
    },
    "server" : "localhost:27017"
}



向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

汉沽区| 通渭县| 洱源县| 平塘县| 敦化市| 苏尼特左旗| 广宗县| 榆社县| 濮阳县| 南阳市| 灵宝市| 靖安县| 兴化市| 手机| 织金县| 大渡口区| 丰都县| 惠安县| 宽甸| 渝中区| 资兴市| 昌图县| 台江县| 盘锦市| 峨眉山市| 盖州市| 鸡西市| 洛扎县| 通道| 垦利县| 沙洋县| 台东县| 庐江县| 上饶市| 长宁县| 永寿县| 名山县| 遂宁市| 江孜县| 高州市| 来凤县|