索引Index:
索引就是用來加速的混狠,特殊數(shù)據(jù)結構,存在磁盤上(緩存在內存中)咽瓷,保存存儲表數(shù)據(jù)的一小部分數(shù)據(jù)崔挖,可以幫助我們快速查找數(shù)據(jù)贸街,索引中的數(shù)據(jù),會有一個指針指向數(shù)據(jù)行所在磁盤的真正BLOCK位置
優(yōu)點:
1狸相、大大減少了服務器需要掃描的數(shù)據(jù)量
2薛匪、索引可以幫助服務器減少排序或臨時表的使用,(已經排好序的索引)
3脓鹃、索引可以將隨機I/O轉換成順序I/O
三星索引:
一星:索引如果能將相關的記錄放置在一起
二星:索引中數(shù)據(jù)的存儲順序與查找標準中順序一致
三星:如果索引中包含查詢中所需要的全部數(shù)據(jù)(覆蓋索引)
索引類型:
B+Tree 平衡樹索引:每葉子節(jié)點到樹根的距離是相同的逸尖,順序索引
Hash索引:hash桶算法,散列索引
空間(R-Tree)索引:地理空間數(shù)據(jù)索引
全文(Full-text)索引:全文檢索
順序索引:
全值精確匹配:name="neo"
匹配最左前綴:name like "neo%",無效:name like "%neo%",
匹配列前綴
匹配范圍值
精確匹配某一列并范圍匹配另外一列:name="neo" and age > 25
只訪問索引的查詢
{聚簇索引:索引與數(shù)據(jù)挨著放瘸右,索引后續(xù)的指針其實就是數(shù)據(jù)娇跟,記錄文件中的記錄順序與索引順序排序,聚簇索引也稱為主索引尊浓,其他索引為輔助索引}
{非聚簇索引:索引中指定的次序與記錄文件中的記錄次序不一致}
散列索引:
散列函數(shù):分布隨機逞频,分布均勻
mysql索引:根據(jù)存儲引擎的不同支持的索引類型也不同
Myisam存儲引擎:索引文件是{.MYI}纯衍,
InnoDB存儲引擎:索引是表空間的組成部分栋齿,{.ibd},主要是B+Tree索引
建立索引需要考慮的問題:
1襟诸、會做什么樣的查詢瓦堵?其中哪些鍵需要索引?
2歌亲、每個鍵的索引方向是怎么樣的菇用?
3、如何應對擴展陷揪?有沒有種不同的鍵的排列可以使常用數(shù)據(jù)更多地保留在內存中惋鸥?
Mongodb索引:幾乎與關系型數(shù)據(jù)庫支持的索引類型一模一樣
單字段索引杂穷,組合索引,多鍵索引卦绣,空間索引耐量,文本索引,hash索引
db.mycoll.ensureIndex(field[,options])
name,unique,dropDups,sparse
db.mycoll.dropIndex(index_name)
db.mycoll.dropIndexes()
db.mycoll.getIndexes()
db.mycoll.reIndex()
mongodb索引創(chuàng)建:
唯一鍵索引:{"unique":true}
消除重復索引:{"dropDups":true}
索引測試:explain()
指定索引查詢:hint(INDEX_NAME)
索引后臺創(chuàng)建:{"background":true} #默認阻塞建立索引期間的所有請求
mongodb索引管理:system.indexes
索引只能通過ensureIndex,dropIndexes進行system.indexes操作
例子:
# 創(chuàng)建測試文檔數(shù)據(jù)
# for(i=1;i<=100;i++) db.testcoll.insert({name:"user"+i,age:(i%150),address:"#"+i+"tianzhong,shenzhen,china",prefrebooks:["book"+i,"helloworld"]})
# 查看集合所有索引滤港,默認情況下廊蜒,只會以"_id"作為鍵來創(chuàng)建索引
> db.system.indexes.findOne()
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "testdb.testcoll"
}
# 查詢數(shù)據(jù),使用默認索引
> db.testcoll.find({name:"user58"}).explain()
{
"cursor" : "BasicCursor", # 表示沒有使用索引
"isMultiKey" : false,
"n" : 1, # 查詢返回數(shù)據(jù)的文檔數(shù)
"nscannedObjects" : 100, # 掃描objects數(shù)
"nscanned" : 100, # 三秒文檔數(shù)
"nscannedObjectsAllPlans" : 100,
"nscannedAllPlans" : 100,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0, # 花費時間
"server" : "node1:27017",
"filterSet" : false
}
# 創(chuàng)建索引
> db.testcoll.ensureIndex({name:1}) # 創(chuàng)建以name鍵為索引
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
# 查看創(chuàng)建的索引
> db.testcoll.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"name" : "_id_",
"ns" : "testdb.testcoll"
},
{
"v" : 1,
"key" : {
"name" : 1
},
"name" : "name_1", # 索引名字
"ns" : "testdb.testcoll" # 索引的位置溅漾,在數(shù)據(jù)庫集合上
}
]
# 在此執(zhí)行查詢
> db.testcoll.find({name:"user11"}).explain()
{
"cursor" : "BtreeCursor name_1", # 使用name_1索引
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1, # 掃描的數(shù)據(jù)為1個文檔
"nscanned" : 1,
"nscannedObjectsAllPlans" : 1,
"nscannedAllPlans" : 1,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"name" : [
[
"user11",
"user11"
]
]
},
"server" : "node1:27017",
"filterSet" : false
}
# 最左前綴匹配測試山叮,創(chuàng)建以姓名和年齡的索引
db.testcoll.ensureIndex({name:1,age:1})
# 以年齡查詢
> db.testcoll.find({age:{$gt:34,$lt:50}}).explain()
{
"cursor" : "BasicCursor", # 沒有使用任何索引
"isMultiKey" : false,
"n" : 15,
"nscannedObjects" : 100,
"nscanned" : 100,
"nscannedObjectsAllPlans" : 100,
"nscannedAllPlans" : 100,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"server" : "node1:27017",
"filterSet" : false
}
# 創(chuàng)建以年齡和姓名的索引
db.testcoll.ensureIndex({age:1,name:1})
# 在次查詢年齡
> db.testcoll.find({age:{$gt:34,$lt:50}}).explain()
{
"cursor" : "BtreeCursor age_1_name_1", #
"isMultiKey" : false,
"n" : 15,
"nscannedObjects" : 15,
"nscanned" : 15,
"nscannedObjectsAllPlans" : 15,
"nscannedAllPlans" : 15,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"age" : [
[
34,
50
]
],
"name" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
},
"server" : "node1:27017",
"filterSet" : false
}
# mongodb是自動匹配最佳索引,進行搜索
# hint使用
> db.testcoll.find({name:"user12"}).hint("name_1_age_1").explain()
{
"cursor" : "BtreeCursor name_1_age_1", # 根據(jù)指定的索引名稱進行搜索
"isMultiKey" : false,
"n" : 1,
"nscannedObjects" : 1,
"nscanned" : 1,
"nscannedObjectsAllPlans" : 1,
"nscannedAllPlans" : 1,
"scanAndOrder" : false,
"indexOnly" : false,
"nYields" : 0,
"nChunkSkips" : 0,
"millis" : 0,
"indexBounds" : {
"name" : [
[
"user12",
"user12"
]
],
"age" : [
[
{
"$minElement" : 1
},
{
"$maxElement" : 1
}
]
]
},
"server" : "node1:27017",
"filterSet" : false
}
# 問題來了添履,在業(yè)務邏輯上是常使用以name屁倔,或者有時候采用name+age的方式進行搜索,name_1_age_1這個所以符合兩個需求
# 那么name_1這個索引就是累贅暮胧,舒服重復索引汰现,age_1_name_1,不匹配最左前綴索引的使用法則叔壤,也是無用的瞎饲。
mongodb的聚合函數(shù):
count:返回集合中的文檔數(shù)量
# db.testcoll.find().count()
distinct:找出給定鍵的所有不同的值,使用時必須指定集合和鍵
group:類似SQL中的group by
mapreduce