標籤:條件 標識 讀取 mongo idt 技術 條件查詢 mongod 基於
一、簡介
在MongoDB建立索引能提高查詢效率,只需要掃描索引只儲存的這個集合的一小部分,並只把這小部分載入到記憶體中,效率大大的提高,如果沒有建立索引,在查詢時,MongoDB必須執行全表掃描,在資料量大時,效率差別就很明顯,對於包括一個沒有索引的排序操作的查詢,伺服器必須在返回任何結果之前將所有的文檔載入到記憶體中來進行排序。
索引是特殊的資料結構,索引儲存在一個易於遍曆讀取的資料集合中,索引是對資料庫表中一列或多列的值進行排序的一種結構。索引項目的排序支援高效的相等匹配和基於範圍的查詢操作。
從mongoDB 3.0開始ensureIndex被廢棄,使用 createIndex建立索引。
建立索引的文法:
db.collection.createIndex(keys,options)
參數 |
類型 |
描述 |
keys |
document |
一個包含該欄位的欄位和值對的文檔,該文檔的索引鍵和該值描述該欄位的索引類型。對於某個領域的上升索引,指定一個值為1;對於下降的索引,指定一個值為1。 MongoDB支援幾種不同的索引類型,包括文本,空間,和雜湊索引。查看更多資訊的索引類型。 |
options |
document |
在建立索引的時的限制條件 |
二、 索引的基本操作
我們先插入10w條記錄
for(var i=0;i<1000000;i++){ . db. orders.insert({ "onumber" : i, "date" : "2015-07-02", "cname" : "zcy"+i, "items" :[ { "ino" : i, "quantity" : i, "price" : 4.0 },{ "ino" : i+1, "quantity" : i+1, "price" : 6.0 } ] }) }
1. 預設索引
儲存在MongoDB集合中的每個文檔(document)都有一個預設的主鍵“_id“,如果我們在添加新的文檔時,沒有指定“_id“值時,MongoDB會建立一個ObjectId值,並建立會自動建立一個索引在“_id“鍵上,預設索引的名稱是”_id_“,並無法刪除,如下面的命令查看:
>db.orders.getIndexes()
2. 查看索引資訊
返回一個數組,該數組儲存標識和描述集合上現有索引的文檔列表,可以查看我們是否有對某個集合建立索引,並建立哪些索引,方便我們管理。
文法:
>db.collection.getIndexes()
3. 建立單列索引
我們對文檔單個欄位建立索引或者對內嵌文檔的單個欄位建立索引
文法:
db.collection.createIndex({field:boolean} })
boolean:對於某個領域的上升索引,指定一個值為1;對於下降的索引,指定一個值為1。
(1)建立
例子:
db.orders.createIndex({cname:1})
我們對orders集合建立了cname索引,預設的索引名稱是”cname_1“
(2)根據條件查詢文檔,並查看查詢效率怎麼樣
例子:
db.orders.find({"cname":"zcy100000"})
我們查詢orders 集合根據條件cname為zcy100000的文檔
我們測試有建索引和沒建索引在1000000條文檔執行查詢的效率怎麼樣,我們這邊先使用explain()函數,下一篇我們介紹
我們這邊先介紹幾個參數
1) n:當前查詢返回的文檔數量。
2)millis:當前查詢所需時間,毫秒數。
3)indexBounds:當前查詢具體使用的索引
例子:
db.orders.find({"cname":"zcy100000"}).explain()
1)沒建索引時,查詢條件cname為zcy100000的文檔
返回一個記錄,花費1006毫秒,沒使用到索引
2)有建索引,查詢條件cname為zcy100000的文檔
返回一個記錄,花費82毫秒,有使用到cname索引
我們結果是相差很大的,有建索引欄位,查詢效率比較高,在大資料時,差別更明顯。
(3)查詢和排序組合使用
我們查詢集合cname大於zcy100的文檔並對onumber進行降序排序
例子:
db.orders.find({"cname":{$gt:"zcy1000"}}).sort({"onumber":1}).explain()
執行出現錯誤:
"$err" : "Runner error:Overflow sort stage buffered data usage of 33554456 bytes exceeds internal limit of 33554432 bytes",
我們的記憶體只有33554432位元組,對於包括一個沒有索引的排序操作的查詢,伺服器必須在返回任何結果之前將所有的文檔載入到記憶體中來進行排序。
我們對onumber建立索引
db.orders.createIndex({onumber:-1})
這次我們在執行時,可以正常執行,已經減少了記憶體的緩衝的資料
4. 建立複合式索引
我們可以同時對多個鍵建立複合式索引
文法:
db.collection.createIndex({field1:boolean, field2:boolean } })
說明:
db.collection.createIndex({a:1,b:1,c:1 } })
我們對a、b、c進組合建立索引,支援查詢時會用到索引的幾種:
1) a
2) a,b
3) a,b,c
這三中的查詢條件,會使用到索引
(1) 建立複合式索引
我們同時對onumber和cname進行複合式索引
例子:
>db.orders.createIndex({cname:1,onumber:-1})
索引儲存在一個易於遍曆讀取的資料集合中,儲存的資料
{_id:..,"onumber" : 2, "date" : "2015-07-02", "cname" : "zcy1"})
{_id:..,"onumber" : 1, "date" : "2015-07-02", "cname" : "zcy1"})
{_id:..,"onumber" : 1, "date" : "2015-07-02", "cname" : "zcy2"})
(2) 查詢
1)我們對cname和onumber作為查詢條件時
例子:
>db.orders.find({"cname":{$gt:"zcy1000"},"onumber":2000}).explain()
我們查詢條件cname大於zcy1000並且onumber等於2000的資料,我們用explain()查詢索引使用方式
2)我們只用兩個索引其中一個作為查詢時
第一種情況:我們條件只使用"cname":{$gt:"zcy1000"}作為查詢條件
例子:
>db.orders.find({"cname":{$gt:"zcy1000"}}).explain()
會使用到索引,符合我們前面介紹的我們對a、b、c進組合建立索引,支援查詢時會用到索引的第一種。
第二種情況:我們條件只使用"onumber":2000作為查詢條件
例子:
> db.orders.find({"onumber":2000}).explain()
不會使用到索引,不符合我們前面介紹的我們對a、b、c進組合建立索引,支援查詢時會用到幾種。
(3)查詢和排序組合使用
我們查詢集合cname大於zcy100的文檔並對onumber進行降序排序
例子:
>db.orders.find({"cname":{$gt:"zcy1000"}}).sort({"onumber":1}).explain()
執行出現錯誤:
"$err" : "Runner error:Overflow sort stage buffered data usage of 33554456 bytes exceeds internal limit of 33554432 bytes",
sort時,不會使用到索引,不符合我們前面介紹的我們對a、b、c進組合建立索引,支援查詢時會用到幾種。
總結:我們在使用複合式索引時,查詢時會用到複合式索引的前端的幾種組合。
我們對a、b、c進組合建立索引,支援查詢時會用到索引的幾種:
1) a
2) a,b
3) a,b,c
5. 內嵌文檔的索引
我們對內嵌文檔建立索引時,跟基本文檔建立索引一樣
文法:
db.collection.createIndex({field:boolean} })
field說明:以“.“來指明內嵌文檔的路徑
(1) 單列的內嵌文檔的索引建立
例子:
>db.orders.createIndex({"items.info":1})
我們orders集合下的內嵌items集合的info欄位建立索引
我們以items.info欄位作為查詢條件,並使用索引的情況
例子:
db.orders.find({"items.info":{$lt:100}}).explain()
我們查詢items.info小於100的資料
(2) 組合的內嵌文檔的索引的建立
我們對內嵌文檔建立複合式索引時,跟基本文檔建立複合式索引一樣
文法:
>db.collection.createIndex({field1:boolean, field2:boolean } })
例子:
>db.orders.createIndex({"items.info":1, "items. quantity":-1})
6. 刪除索引
我們對已經建立的索引進行刪除,可以針對具體的集合中索引進行刪除,也可以對所有的集合中的所有索引刪除
(1)具體索引名稱刪除索引
文法:
db.collection.dropIndex(index)
刪除具體的索引,根據索引名稱刪除,如果不知道索引的名稱,可以通過db.collection.getIndexes()查看索引名稱
例子:
> db.orders.dropIndex("cname_1")
我們刪除cname欄位的索引,現在只剩下onumber欄位索引
(2)刪除集合中所有索引
文法:
db.collection.dropIndexes()
例子:
> db.orders.dropIndexes()
我們對集合中的索引都刪除,我們刪除cname欄位的索引和onumber欄位索引,現在只剩預設的_id欄位索引,索引我們在使用時,要謹慎,以免把集合中的索引都刪除。
(3)對dropIndexes方法,我們還有一種用法,可以指定集合的具體索引的刪除
例子:
> db.runCommand({"dropIndexes":"orders","index":"cname_1"})
我們刪除cname欄位的索引,現在只剩下onumber欄位索引
總結:
在MongoDB建立索引能提高查詢效率,但在MongoDB新增、修改效率上比較慢
MongoDB-6: MongoDB索引