设为首页 收藏本站
查看: 1160|回复: 0

[经验分享] MongoDB(三)

[复制链接]

尚未签到

发表于 2018-10-26 08:46:32 | 显示全部楼层 |阅读模式
  一、MongoDB索引
  1、索引介绍
  索引在mongodb中被支持,如果没有索引,mongodb必须扫描每一个文档集合选择匹配的查询记录。这样扫描集合效率并不高,因为它需要mongod进程使用大量的数据作遍历操作。 索引是一种特殊的数据结构,它保存了小部分简单的集合数据。索引存储了一些特殊字段,并将其排序。
  从根本上讲,索引在mongodb中和其他数据库系统是类似的。mongodb规定了索引的集合级别、支持索引任何字段或者子字段在mongodb文档集合中。
  2、索引优化查询方案

  •   要考虑数据之间的关系,做查询优化。
  •   创建索引支持常见的面向用户的查询,确保扫描读取文件最小数量。
  •   索引可以优化特定场景中的其它业务的性能。
  3、排序返回数据
  来看看一个索引的具体例子(其实就相当于我们查询字段一样的)
DSC0000.jpg

  4、索引类型
  MongoDB提供了一些不同的索引类型支持的数据和查询的具体类型

  •   Default _id (默认_id索引) :所有mongodb默认都有一个_id字段索引,如果我们不指定_id的值会自动生成一个ObjectId值。 该_id索引是唯一的,并且可以防止客户端对_id字段值相同插入两个。
# 查询articles集合的索引  
db.articles.getIndexes();
  
# 添加titlei字段索引,并且为升序
  
db.articles.ensureIndex({title:1});
  
#重构索引(慎用)
  
db.articles.reIndex();
  注意:索引排序规则升序:1,降序-1

  •   Single Field (单字段索引) :mongodb允许定义单个字段的索引,与default _id一样,只是字段不同。


  •   Compound Index (复合索引[多字段索引]) :mongodb中可以自定多个字段的索引。例如,如果一个复合指标包括{userid:1,score:-1 },索引排序第一的用户名后,在每一个用户标识符值,按得分++倒序++排序。
{  
    "_id": ObjectId(...),
  
    "item": "Banana",
  
    "category": ["food", "produce", "grocery"],
  
    "location": "4th Street Store",
  
    "stock": 4,
  
    "type": "cases",
  
    "arrival": Date(...)
  
}
  创建方法:
# 创建item、stock字段的复合索引,并且升序排序  
db.products.ensureIndex( { "item": 1, "stock": 1 } )
  
注意:Hashed 字段不能创建索引,如果创建将出现错误
  
Application Sort Order 使用案例:降序用户名升序时间。
  
# 查询结果集中排序
  
db.events.find().sort( { username: -1, date: 1 } )
  
# 查询结果集中排序
  
db.user_scores.find().sort({score:-1,date:-1}).limit(1)

  •   MultiKey Index (多键索引)
  官方文档中给出这样一个案例:
{  
    userid:"marker",
  
    address:[
  
        {zip:"618255"},
  
        {zip:"618254"}
  
    ]
  
}
  
# 创建索引,并将zip升序排列
  
db.users.ensureIndex({"address.zip": 1});
  
# 假如我们做这样的查询
  
db.users.find({"addr":{"$in":[{zip:"618254"}]}})
  注意:你可以创建 多键复合索引(multikey compound indexes)

  •   Geospatial Index (地理空间索引)
  db.places.ensureIndex( { loc : "2dsphere" } )

  •   Text Indexes (文本索引) :文本索引是在2.4版本更新的,提供了文本搜索文档中的集合功能,文本索引包含:字符串、字符数组。使用$text做查询操作。 2.6版本 默认情况下使文本搜索功能。在MongoDB 2.4,你需要使文本搜索功能手动创建全文索引和执行文本搜索
# 创建文本索引  
db.articles.ensureIndex({content:"text"});
  复合索引可以包含文本索引 称为:复合文本索引(compound text indexes),但有限制 :

  •   复合文本索引不能包含任何其他特殊索引类型,比如:多键索引(multi-key Indexes)
  •   如果复合文本索引包含文本索引的键,执行$text查询必须相同查询条件。可能翻译不对原文:
  (If the compound text index includes keys preceding the text index key, to perform a $text search, the query
  predicate must include equality match conditions on the preceding keys1)

  •   Hashed Indexes (哈希码索引) :哈希索引在2.4版本更新的,将实体的的哈希值作为索引字段,
  # 给user_scores的score字段创建一个哈希索引
  db.user_scores.ensureIndex( { score: "hashed" } )
  5、索引的属性
  除了众多索引类型的支持以外,还可以使用各种属性来调整性能。

  •   TTL Indexes :它是一个特殊的索引,可以在某个时间自动的删除文档集合的索引。对于一些信息数据比如说日志、事件对象、会话信息,只需要存放在数据库一个特定期限。
  使用限制:

  •   不支持复合索引
  •   必须是date时间类型字段
  •   如果是date数组,按照最早时间过期。
  注意:TTL index不保证过期时间立即删除,,后台任务没60秒运行删除, 依赖于mongod进程。

  •   Unique Indexes
# 创建唯一索引  
db.members.ensureIndex( { "user_id": 1 }, { unique: true } )
  注意:如果字段为null,那么就以null值,但不能重复插入空值。如果collection中有两个实体唯一索引字段为空,则不能创建唯一索引
  也就是说,我们还可以利用它作为类似于关系型数据库的唯一约束。
# 强制插入空值对象后报错  
> db.users.insert({content:"unique testing"})
  
WriteResult({
  
        "nInserted" : 0,
  
        "writeError" : {
  
                "code" : 11000,
  
                "errmsg" : "insertDocument :: caused by :: 11000 E11000 duplicat
  
e key error index: test.users.$dsadsadsa  dup key: { : null }"
  
        }
  
})

  •   Sparse Indexes
db.addresses.ensureIndex( { "xmpp_id": 1 }, { sparse: true } )

  •   background属性 高效修改/创建索引 :在项目运行中,如果我们直接采用前面的方法创建索引或者修改索引,那么数据库会阻塞建立索引期间的所有请求。mongodb提供了background属性做后台处理。
db.addresses.ensureIndex( { "xmpp_id": 1 }, {background: true } )  我们知道如果阻塞所有请求,建立索引就会很快,但是使用系统的用户就需要等待,影响了数据库的操作,因此可以更具具体情况来选择使用background属性
  6、索引名称
# 自动生成索引名称  
db.products.ensureIndex( { item: 1, quantity: -1 } )
  
# 被命名为: item_1_quantity_-1
  
# 自定义索引名称
  
db.products.ensureIndex( { item: 1, quantity: -1 } , { name: "inventory" } )
  7 、管理索引
# 添加/修改索引  
db.users.ensureIndex({name:"text"});
  
# 删除集合所有索引
  
db.users.dropIndexes();
  
# 删除特定索引 (删除id字段升序的索引)
  
db.users.dropIndex({"id":1})
  
# 获取集合索引
  
db.users.getIndexes();
  
# 重构索引
  
db.users.reIndex();
  8、索引分类

  •   Default _id (默认_id索引)
  •   Single Field (单字段索引)
  •   Compound Index (复合索引[多字段索引])
  •   MultiKey Index (多键索引)
  •   Geospatial Index (地理空间索引)
  •   Text Indexes (文本索引)
  •   Hashed Indexes (哈希码索引)
  二、应用举例
  创建单字段索引:
> db.testcoll.ensureIndex({Name: 1})  
> db.testcoll.getIndexes()
  
[
  
{
  
  "v" : 1,
  
  "name" : "_id_",
  
  "key" : {
  
   "_id" : 1
  
  },
  
  "ns" : "test.testcoll"
  
},
  
{
  
  "v" : 1,
  
  "name" : "Name_1",
  
  "key" : {
  
   "Name" : 1
  
  },
  
  "ns" : "test.testcoll"
  
}
  
]
  创建哈希索引:
> db.testcoll.ensureIndex({Name: "hashed"})  
> db.testcoll.getIndexes()
  
[
  
{
  
  "v" : 1,
  
  "name" : "_id_",
  
  "key" : {
  
   "_id" : 1
  
  },
  
  "ns" : "test.testcoll"
  
},
  
{
  
  "v" : 1,
  
  "name" : "Name_1",
  
  "key" : {
  
   "Name" : 1
  
  },
  
  "ns" : "test.testcoll"
  
},
  
{
  
  "v" : 1,
  
  "name" : "Name_hashed",
  
  "key" : {
  
   "Name" : "hashed"
  
  },
  
  "ns" : "test.testcoll"
  
}
  
]
  删除哈希索引:
> db.testcoll.dropIndex("Name_hashed")  
{ "nIndexesWas" : 3, "ok" : 1 }
  
> db.testcoll.getIndexes()
  
[
  
{
  
  "v" : 1,
  
  "name" : "_id_",
  
  "key" : {
  
   "_id" : 1
  
  },
  
  "ns" : "test.testcoll"
  
},
  
{
  
  "v" : 1,
  
  "name" : "Name_1",
  
  "key" : {
  
   "Name" : 1
  
  },
  
  "ns" : "test.testcoll"
  
}
  
]
  删除单字段索引:
> db.testcoll.dropIndex({Name: 1})  
{ "nIndexesWas" : 2, "ok" : 1 }
  
> db.testcoll.getIndexes()
  
[
  
{
  
  "v" : 1,
  
  "name" : "_id_",
  
  "key" : {
  
   "_id" : 1
  
  },
  
  "ns" : "test.testcoll"
  
}
  
]
  删除所有索引:
> db.testcoll.dropIndexes()  查看索引是否用到:
> db.testcoll.find({Name:  "User:88"}).explain()  
{
  
"cursor" : "BasicCursor",
  
"isMultiKey" : false,
  
"n" : 1,
  
"nscannedObjects" : 100,
  
"nscanned" : 100,
  
"nscannedObjectsAllPlans" : 100,
  
"nscannedAllPlans" : 100,
  
"scanAndOrder" : false,
  
"indexOnly" : false,
  
"nYields" : 0,
  
"nChunkSkips" : 0,
  
"millis" : 42,
  
"indexBounds" : {
  

  
},
  
"server" : "www.example.com:27017"
  
}
  
> db.testcoll.find().count()
  
100
  通过创建索引可以发现在查询时只需要一次就行,不用在全文档扫描:
> db.testcoll.ensureIndex({Name: 1}),{unique: true}  
{ "unique" : true }
  
> db.testcoll.find({Name:  "User:88"}).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" : [
  
[
  
"User:88",
  
"User:88"
  
]
  
]
  
},
  
"server" : "www.example.com:27017"
  
}
  指定索引查询:
> db.testcoll.find({Name:  "User:88"}).hint({Name: 1}).explain()  总结:
  前面只是简单的介绍了MongoDB的索引及其的使用,在查询时我们最好可以根据创建的索引来进行查询,这样做可以大大节省磁盘IO的开销。若查询时没有相关的索引则极可能遍历全部文档,这样大大降低了性能。在实际使用中创建和使用索引要做到:根据实际的需求创建最合适索引,查询时也要使用最合适的索引。对于索引的使用前面所讲的只是一些皮毛知识,若想深入学习建议可以查阅《数据库索引设计与优化》。



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-626565-1-1.html 上篇帖子: MongoDB安装及用户名密码管理 下篇帖子: mongodb 集群安 装
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表