额外开销
每个索引占据一定的存储空间,在进行插入,更新和删除操作时也需要对索引进行操作。所以,如果你很少对集合进行读取操作,建议不使用索引。
内存(RAM)使用由于索引是存储在内存(RAM)中,你应该确保该索引的大小不超过内存的限制。
如果索引的大小大于内存的限制,MongoDB会删除一些索引,这将导致性能下降。
查询限制索引不能被以下的查询使用:
所以,检测你的语句是否使用索引是一个好的习惯,可以用explain来查看。
索引键限制从2.6版本开始,如果现有的索引字段的值超过索引键的限制,MongoDB中不会创建索引。
插入文档超过索引键限制如果文档的索引字段值超过了索引键的限制,MongoDB不会将任何文档转换成索引的集合。与mongorestore和mongoimport工具类似。
最大范围MongoDB 索引限制
标签:
小编还为您整理了以下内容,可能对您也有帮助:
MongoDB 索引
Nothing like a little truth to sober you up.
唯有事实最能让人清醒。
索引支持在MongoDB中高效地执行查询。如果没有索引,MongoDB必须执行全集合扫描,即扫描集合中的每个文档,以选择与查询语句匹配的文档。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。
如果查询存在适当的索引,MongoDB可以使用该索引必须检查的文档数。
索引是特殊的数据结构,它以易于遍历的形式存储集合数据集的一小部分。索引存储特定字段或一组字段的值,按字段值排序。索引项的排序支持有效的相等匹配和基于范围的查询操作。此外,MongoDB还可以使用索引中的排序返回排序结果。
官网文档: https://docs.mongodb.com/manual/indexes/
MongoDB索引使用B树数据结构(确切的说是B-Tree,MySQL是B+Tree)
MongoDB的索引可以分为:单字段索引、复合索引以及地理空间索引等。
单字段索引:MongoDB支持在文档的单个字段上创建用户定义的升序/降序索引,称为单字段索引(Single Field Index)。
对于单个字段索引和排序操作,索引键的排序顺序(即升序或降序)并不重要,因为MongoDB可以在任何方向上遍历索引。
复合索引:MongoDB还支持多个字段的用户定义索引,即复合索引(Compound Index)。
复合索引中列出的字段顺序具有重要意义。例如,如果复合索引由 { userid: 1, score: -1 } 组成,则索引首先按userid正序排序,然后在每个userid的值内,再在按score倒序排序。
其他索引:
地理空间索引(Geospatial Index):为了支持对地理空间坐标数据的有效查询,MongoDB提供了两种特殊的索引:返回结果时使用平面几何的二维索引和返回结果时使用球面几何的二维球面索引。
文本索引(Text Indexes):MongoDB提供了一种文本索引类型,支持在集合中搜索字符串内容。这些文本索引不存储特定于语言的停止词(例如“the”、“a”、“or”),而将集合中的词作为词干,只存储根词。
哈希索引(Hashed Indexes):为了支持基于散列的分片,MongoDB提供了散列索引类型,它对字段值的散列进行索引。这些索引在其范围内的值分布更加随机,但只支持相等匹配,不支持基于范围的查询。
查看索引
返回一个集合中的所有索引的数组
语法格式 : db.collection.getIndexes()
提示 :该语法命令运行要求是MongoDB 3.0+
示例
结果中显示的是默认 _id 索引。
默认_id索引 :MongoDB在创建集合的过程中,在 _id 字段上创建一个唯一的索引,默认名字为 id ,该索引可防止客户端插入两个具有相同值的文档,您不能在_id字段上删除此索引。
注意 :该索引是唯一索引,因此值不能重复,即 _id 值不能重复的。在分片集群中,通常使用 _id 作为片键。
创建索引
在集合上创建索引。
语法格式 : db.collection.createIndex(keys, options)
参数说明 :
options(更多选项)列表:
注意 :在 3.0.0 版本前创建索引方法为 db.collection.ensureIndex() ,之后的版本使用了 db.collection.createIndex() 方法, ensureIndex() 还能用,但只是 createIndex() 的别名。
实例
移除索引
可以移除指定的索引,或移除所有索引
语法格式 : db.collection.dropIndex(index) 或移除所有索引 db.collection.dropIndexes()
参数说明 :
实例
提示 : _id 的字段的索引是无法删除的,只能删除非 _id 字段的索引。
执行计划
分析查询性能(Analyze Query Performance)通常使用执行计划(解释计划、Explain Plan)来查看查询的情况,如查询耗费的时间、是否基于索引查询等。
那么,通常,我们想知道,建立的索引是否有效,效果如何,都需要通过执行计划查看。
语法格式 : db.collection.find(query,options).explain(options)
实例
涵盖查询Covered Queries
当查询条件和查询的投影仅包含索引字段时,MongoDB直接从索引返回结果,而不扫描任何文档或将文档带入内存。 这些覆盖的查询可以非常有效。
我的理解是类似于mysql的索引覆盖,无须回表查询。
实例
有故事的人,通常不喜欢讲故事。不想在嘴上卖力,是想在心中开发能量。沉默,是一种负重的坚强,是一种韬光养晦的低调。少说多做,才是最有力的践行。
李老师 mongoDB中 字符类型的字段 有大小长度限制吗
NUMBER类型字段的长度固定是22。
DATA类型字段的长度固定是7。
索引默认是升序,如果要降序建的索引长度是字段定义长度*1.5+1。
MYSQL对索引长度*比较复杂,每种版本及存储引擎都不一样,如下是MYSQL5.1.58测试的结果:
INNODB的最大总长度是3072字节,单个字符字段是767字节,如果字段长度大于767则自动截取前767个字符。
MYISAM最大总长度是1000字节,单个字符字段是1000字节。
MEMORY的最大总长度是3072字节,单个字符字段是3072字节。
李老师 mongoDB中 字符类型的字段 有大小长度限制吗
NUMBER类型字段的长度固定是22。
DATA类型字段的长度固定是7。
索引默认是升序,如果要降序建的索引长度是字段定义长度*1.5+1。
MYSQL对索引长度*比较复杂,每种版本及存储引擎都不一样,如下是MYSQL5.1.58测试的结果:
INNODB的最大总长度是3072字节,单个字符字段是767字节,如果字段长度大于767则自动截取前767个字符。
MYISAM最大总长度是1000字节,单个字符字段是1000字节。
MEMORY的最大总长度是3072字节,单个字符字段是3072字节。
mongodb 索引是什么数据结构
MongoDB索引使用B-tree数据结构。
索引支持MongoDB中查询的高效执行。如果没有索引,MongoDB必须执行集合扫描,即扫描集合中的每个文档,以选择与查询语句匹配的文档。如果查询存在适当的索引,MongoDB可以使用索引来*它必须检查的文档数。
扩展资料
MongoDB索引的类型
1、单字段索引(Single Field Index)
这个是最简单最常用的索引类型,比如我们上边的例子,为id建立一个单独的索引就是此种类型。
2、复合索引(Compound Index)
索引field的先后顺序很关键,影响有两方面:
(1)MongoDB在复合索引中是根据prefix排序查询,就是说排在前面的可以单独使用。
(2)过滤出的document越少的field越应该放在前面,比如此例中id如果是唯一的,那么就应该放在最前面,因为这样通过id就可以锁定唯一一个文档。而如果通过city或者score过滤完成后还是会有大量文档,这就会影响最终的性能。
索引的排序顺序不同:复合索引最末尾的field,其排序顺序不同对于MongoDB的查询排序操作是有影响的。
3、多key索引(Multikey Index):主要针对数据类型为数组的类型。
4、其它类型索引:另外,MongoDB中还有其它如哈希索引,地理位置索引以及文本索引,主要用于一些特定场景。
mongodb 索引是什么数据结构
MongoDB索引使用B-tree数据结构。
索引支持MongoDB中查询的高效执行。如果没有索引,MongoDB必须执行集合扫描,即扫描集合中的每个文档,以选择与查询语句匹配的文档。如果查询存在适当的索引,MongoDB可以使用索引来*它必须检查的文档数。
扩展资料
MongoDB索引的类型
1、单字段索引(Single Field Index)
这个是最简单最常用的索引类型,比如我们上边的例子,为id建立一个单独的索引就是此种类型。
2、复合索引(Compound Index)
索引field的先后顺序很关键,影响有两方面:
(1)MongoDB在复合索引中是根据prefix排序查询,就是说排在前面的可以单独使用。
(2)过滤出的document越少的field越应该放在前面,比如此例中id如果是唯一的,那么就应该放在最前面,因为这样通过id就可以锁定唯一一个文档。而如果通过city或者score过滤完成后还是会有大量文档,这就会影响最终的性能。
索引的排序顺序不同:复合索引最末尾的field,其排序顺序不同对于MongoDB的查询排序操作是有影响的。
3、多key索引(Multikey Index):主要针对数据类型为数组的类型。
4、其它类型索引:另外,MongoDB中还有其它如哈希索引,地理位置索引以及文本索引,主要用于一些特定场景。
spring mongo 怎么建立索引
1.创建索引
1)创建单个索引
db.collection.ensureIndex({a:1})
在a字段上创建一个升序的索引(对于单个字段的索引,升序或是降序都一样)。
2)创建复合索引
db.collection.ensureIndex({a:1,b:-1})
3)创建稀疏索引
db.collection.ensureIndex({a:1},{sparse:true})
索引中将不包含没有a字段的文档。
4)创建唯一索引
db.collection.ensureIndex({a:1},{unique:true})
为a字段建立唯一索引。
当mongo要索引一个字段时,如果一篇文档中没有这个字段,这篇文档就会被索引为null,
因为唯一索引不能有重复值,所以必须和稀疏索引配合使用,如:
db.collection.ensureIndex({a:1},{unique:true,sparse:true})
复合索引也可以加唯一*,如:
db.collection.ensureIndex({a:1,b:1},{unique:true})
5)在后台创建索引
db.collection.ensureIndex({a:1},{background:true})
6)丢弃重复数据
要强制在一个有重复数据的字段上创建唯一索引,可以使用dropDups选项,这会强制mongo
在创建唯一索引时删除重复数据(危险操作),如:
db.collection.ensureIndex({a:1},{dropDups:true})
2.查看索引
1)查看某个库上的所有索引
db.system.index.find()
2)查看某个表上的所有索引
db.collection.getIndexes()
3.删除索引
1)删除表上的某个索引
db.collection.dropIndex({a:1})
2)删除表上的所有索引
db.collection.dropIndexes()
4.重建索引
db.collection.reIndex()
以上操作会删除表上的所有索引(包含_id)并重建所有索引。
5.在副本集上创建索引
后台创建索引操作在一个副本集的从节点(secondary)上会变成前台操作,这时创建索引的操作会
阻塞从节点上的所有的复制和读操作。
从节点会在主节点完成创建索引的操作后开始创建索引,在分片集群环境(sharded cluster)中,
mongos会向每个分片上的副本集环境的主节点发送ensureIndex(),然后在主节点完成创建索引后
复制到从节点上。
为了在副本集环境中将创建索引的影响降低到最小,使用以下方法在从节点上创建索引:
1)在一个从节点上停止mongod进程,使用另一个端口号不采用–replSet选项重启mongod进程,这
个mongod实例现在已”独立”(standalone)模式运行;
2)在这个mongod实例上创建新索引或者重建索引;
3)采用–replSet选项重启mongod实例。允许复制操作catch up这个成员;
4)在其它的从节点上重复这个操作;
5)在这个集(set)上的主节点上运行rs.stepDown(),然后在之前的主节点上重复这个过程。
6.索引中的升序键和降序键
对于单个键的索引,键的顺序没有关系。但是对于符合索引,键的升、降顺序有很大影响。
比如说一个表包含用户名(username)和该用户发表文章的时间(time),如果你需要经常查询某用户最
新发表的文章,你应该创建这样的索引:
db.collection.ensureIndex({“username”:1,”time”:-1})
7.索引的*
1)一个表上的索引不能超过64个;
2)索引的键不能超过1024bytes();
3)索引的名字(包含命名空间)必须少于128个字符;
8.索引策略
MongoDB对于每个操作只能使用一个索引,$or的每一个子句可以使用自己的索引。
对于下边的索引:
db.collection.ensureIndex({“category”:1,”item”:1})
无论单独查询category、item,还是两者一起查询,该索引都有效。但是有个例外,使用$or操作符时,
一个查询不能使用复合索引,只能使用单个索引。
一个多字段的复合索引可以支持所有在这些字段上就前缀子集进行查询的需求,例如:
db.collection.ensureIndex({x:1,y:1,z:1})
以上索引可以支持如下查询需求:
db.collection.find({x:232})
db.collection.find({x:232,y:3})
db.collection.find({x:232,y:3,z:34})
索引{x:1,y:1,z:1}可以支持一些索引{x:1,z:1}支持的查询?
对于查询db.collection.find({x:5}).sort({z:1}),索引{x:1,z:1}既支持查询页支持排序,而索引
{x:1,y:1,z:1}只支持查询?
使用索引为查询的结果排序:
比如有这样一个索引
db.collection.ensureIndex({a:1,b:1,c:1,d:1})
以下的查询和排序操作可以使用索引:
db.collection.find().sort({a:1})
db.collection.find().sort({a:1,b:1})
db.collection.find({a:4}).sort({a:1,b:1})
db.collection.find({b:5}).sort({a:1,b:1})
db.collection.find({a:5}).sort({b:1,c:1})
db.collection.find({a:5,c:4,b:3}).sort({d:1})
db.collection.find({a:{$gt:4}}).sort({a:1,b:1})
db.collection.find({a:{$gt:5}}).sort({a:1,b:1})
db.collection.find({a:5, b:3,d:{$gt:4}}).sort({c:1})
db.collection.find({a:5, b:3,c:{$lt:2},d:{$gt:4}}).sort({c:1})
以下的查询和排序不能使用索引:
db.collection.find().sort( { b:1 } )
db.collection.find( { b:5 } ).sort( { b:1 } )
对于不使用索引的sort()操作,当使用超过32Mb内存时,sort()操作将退出。
spring mongo 怎么建立索引
1.创建索引
1)创建单个索引
db.collection.ensureIndex({a:1})
在a字段上创建一个升序的索引(对于单个字段的索引,升序或是降序都一样)。
2)创建复合索引
db.collection.ensureIndex({a:1,b:-1})
3)创建稀疏索引
db.collection.ensureIndex({a:1},{sparse:true})
索引中将不包含没有a字段的文档。
4)创建唯一索引
db.collection.ensureIndex({a:1},{unique:true})
为a字段建立唯一索引。
当mongo要索引一个字段时,如果一篇文档中没有这个字段,这篇文档就会被索引为null,
因为唯一索引不能有重复值,所以必须和稀疏索引配合使用,如:
db.collection.ensureIndex({a:1},{unique:true,sparse:true})
复合索引也可以加唯一*,如:
db.collection.ensureIndex({a:1,b:1},{unique:true})
5)在后台创建索引
db.collection.ensureIndex({a:1},{background:true})
6)丢弃重复数据
要强制在一个有重复数据的字段上创建唯一索引,可以使用dropDups选项,这会强制mongo
在创建唯一索引时删除重复数据(危险操作),如:
db.collection.ensureIndex({a:1},{dropDups:true})
2.查看索引
1)查看某个库上的所有索引
db.system.index.find()
2)查看某个表上的所有索引
db.collection.getIndexes()
3.删除索引
1)删除表上的某个索引
db.collection.dropIndex({a:1})
2)删除表上的所有索引
db.collection.dropIndexes()
4.重建索引
db.collection.reIndex()
以上操作会删除表上的所有索引(包含_id)并重建所有索引。
5.在副本集上创建索引
后台创建索引操作在一个副本集的从节点(secondary)上会变成前台操作,这时创建索引的操作会
阻塞从节点上的所有的复制和读操作。
从节点会在主节点完成创建索引的操作后开始创建索引,在分片集群环境(sharded cluster)中,
mongos会向每个分片上的副本集环境的主节点发送ensureIndex(),然后在主节点完成创建索引后
复制到从节点上。
为了在副本集环境中将创建索引的影响降低到最小,使用以下方法在从节点上创建索引:
1)在一个从节点上停止mongod进程,使用另一个端口号不采用–replSet选项重启mongod进程,这
个mongod实例现在已”独立”(standalone)模式运行;
2)在这个mongod实例上创建新索引或者重建索引;
3)采用–replSet选项重启mongod实例。允许复制操作catch up这个成员;
4)在其它的从节点上重复这个操作;
5)在这个集(set)上的主节点上运行rs.stepDown(),然后在之前的主节点上重复这个过程。
6.索引中的升序键和降序键
对于单个键的索引,键的顺序没有关系。但是对于符合索引,键的升、降顺序有很大影响。
比如说一个表包含用户名(username)和该用户发表文章的时间(time),如果你需要经常查询某用户最
新发表的文章,你应该创建这样的索引:
db.collection.ensureIndex({“username”:1,”time”:-1})
7.索引的*
1)一个表上的索引不能超过64个;
2)索引的键不能超过1024bytes();
3)索引的名字(包含命名空间)必须少于128个字符;
8.索引策略
MongoDB对于每个操作只能使用一个索引,$or的每一个子句可以使用自己的索引。
对于下边的索引:
db.collection.ensureIndex({“category”:1,”item”:1})
无论单独查询category、item,还是两者一起查询,该索引都有效。但是有个例外,使用$or操作符时,
一个查询不能使用复合索引,只能使用单个索引。
一个多字段的复合索引可以支持所有在这些字段上就前缀子集进行查询的需求,例如:
db.collection.ensureIndex({x:1,y:1,z:1})
以上索引可以支持如下查询需求:
db.collection.find({x:232})
db.collection.find({x:232,y:3})
db.collection.find({x:232,y:3,z:34})
索引{x:1,y:1,z:1}可以支持一些索引{x:1,z:1}支持的查询?
对于查询db.collection.find({x:5}).sort({z:1}),索引{x:1,z:1}既支持查询页支持排序,而索引
{x:1,y:1,z:1}只支持查询?
使用索引为查询的结果排序:
比如有这样一个索引
db.collection.ensureIndex({a:1,b:1,c:1,d:1})
以下的查询和排序操作可以使用索引:
db.collection.find().sort({a:1})
db.collection.find().sort({a:1,b:1})
db.collection.find({a:4}).sort({a:1,b:1})
db.collection.find({b:5}).sort({a:1,b:1})
db.collection.find({a:5}).sort({b:1,c:1})
db.collection.find({a:5,c:4,b:3}).sort({d:1})
db.collection.find({a:{$gt:4}}).sort({a:1,b:1})
db.collection.find({a:{$gt:5}}).sort({a:1,b:1})
db.collection.find({a:5, b:3,d:{$gt:4}}).sort({c:1})
db.collection.find({a:5, b:3,c:{$lt:2},d:{$gt:4}}).sort({c:1})
以下的查询和排序不能使用索引:
db.collection.find().sort( { b:1 } )
db.collection.find( { b:5 } ).sort( { b:1 } )
对于不使用索引的sort()操作,当使用超过32Mb内存时,sort()操作将退出。
mongodb建立索引&查看索引&删除索引
从Robo 3T可视化界面中,去创建mongodb数据表的索引。
1.数据表结构:{_id:value, doc_city:value, doc_province:value, content, judgementId}
2.content字段展开:
3.对content字段里的title/caseType/judgementType建立索引
db.getCollection('chongqing').createIndex({"content.title":1, "content.judgementType":1, "content.caseType":1})
4.让创建索引的过程在后台运行
db.getCollection('chongqing').createIndex({"content.title":1, "content.judgementType":1, "content.caseType":1},{background:true})
5.查询集合索引
db.getCollection('chongqing').getIndexes()
6.查看索引集合大小
db.getCollection('chongqing').totalIndexSize()
7.删除集合所有索引
db.getCollection('chongqing').dropIndexes()
8.删除集合指定索引
db.getCollection('chongqing').dropIndex('索引名')
mongodb的复合索引是怎么回事?例如db.a.ensureIndex({i:1,j:-1}...
复合索引或者是索引的目的是方便后续的查找,在在MongoDB中, 数字1表示i键的索引按升序存储,-1表示j键的索引按照降序方式存储。
> db.test.ensureIndex({"i":1,
"j":-1})
该索引被创建后,基于i和j的查询将会用到该索引,或者是基于i的查询也会用到该索引,但是只是基于j的查询将不会用到该复合索引。因此可以说,如果想用到复合索引,必须在查询条件中包含复合索引中的前N个索引列。然而如果查询条件中的键值顺序和复合索引中的创建顺序不一致的话,MongoDB可以智能的帮助我们调整该顺序,以便使复合索引可以为查询所用。
所以这个索引主要是为了建立一个数据的排放方式方便后续的查找,但是对于一个键的排序只有一个方向,但是不同的键排序方向可以不一样。追问复合索引应该是整体作为索引键吧,而不是以 i 或者 j 作为索引键;按你的说法就是 i 或者 j 单独作为索引键;
追答是将整体作为索引,但是他的排序是有顺序的,第一个是最先考虑的,然后才是第二个。。。从这个角度上说,如果你需要索引i的话,你用这个复合索引也可以获得结果,但是你索引j就不可以,因为这个复合索引是首先考虑i,然后再考虑j的。
mongodb的复合索引是怎么回事?例如db.a.ensureIndex({i:1,j:-1}...
复合索引或者是索引的目的是方便后续的查找,在在MongoDB中, 数字1表示i键的索引按升序存储,-1表示j键的索引按照降序方式存储。
> db.test.ensureIndex({"i":1,
"j":-1})
该索引被创建后,基于i和j的查询将会用到该索引,或者是基于i的查询也会用到该索引,但是只是基于j的查询将不会用到该复合索引。因此可以说,如果想用到复合索引,必须在查询条件中包含复合索引中的前N个索引列。然而如果查询条件中的键值顺序和复合索引中的创建顺序不一致的话,MongoDB可以智能的帮助我们调整该顺序,以便使复合索引可以为查询所用。
所以这个索引主要是为了建立一个数据的排放方式方便后续的查找,但是对于一个键的排序只有一个方向,但是不同的键排序方向可以不一样。追问复合索引应该是整体作为索引键吧,而不是以 i 或者 j 作为索引键;按你的说法就是 i 或者 j 单独作为索引键;
追答是将整体作为索引,但是他的排序是有顺序的,第一个是最先考虑的,然后才是第二个。。。从这个角度上说,如果你需要索引i的话,你用这个复合索引也可以获得结果,但是你索引j就不可以,因为这个复合索引是首先考虑i,然后再考虑j的。
rails 如何从mongodb 中取出某索引值的最大值
索引通常能够极大的提高查询的效率。在系统中使用查询时,应该考虑建立相关的索引。在MongoDB中创建索引相对比较容易。
MongoDB中的索引在概念上和大多数关系型数据库如MySQL是一样的。当你在某种情况下需要在MySQL中建立索引,这样的情景同样适合于MongoDB。
基本操作
索引是一种数据结构,他搜集一个集合中文档特定字段的值。MongoDB的查询优化器能够使用这种数据结构来快速的对集合(collection)中的文档(collection)进行寻找和排序.准确来说,这些索引是通过B-Tree索引来实现的。
在命令行中,可以通过调用ensureIndex()函数来建立索引,该函数指定一个到多个需要索引的字段。沿用在前面的随笔中的例子,我们再things集合中的j字段上建立索引:
1. >
db.things.ensureIndex({j:1})
EnsureIndex()函数自是在索引不存在的情况下才会创建。
一旦集合在某一个字段上建立索引后,对该字段的随机查询的访问速度会很快。如果没有索引,MongoDB会在遍历所有的键值对,然后去对应检查相关的字段。
1. >
db.things.find({j:2}); //在建立了索引的字段上查询,速度快
2.
3. { "_id" :
ObjectId("4e24433dcac1e3490b9033be"), "x" : 4, "j" : 2 }
4.
5. >
db.things.find({x:3});//在未建立索引的字段上查询,需要逐个字段匹配,速度慢
6.
7. { "_id" :
ObjectId("4e244315cac1e3490b9033bc"), "x" : 3
}
通过在命令行中输入getIndexs()能够查看当前集合中的所有索引。
1. >
db.things.getIndexes()
2.
3. [
4.
5. {
6.
7. "name"
: "_id_",
8.
9. "ns" : "things.things",
10.
11. "key" :
{
12.
13. "_id" : 1
14.
15. },
16.
17. "v" :
0
18.
19. },
20.
21. {
22.
23. "_id" :
ObjectId("4e244382cac1e3490b9033d0
24.
25. "ns" :
"things.things",
26.
27. "key" : {
28.
29. "j" :
1
30.
31. },
32.
33. "name" : "j_1",
34.
35. "v" :
0
36.
37. }
38.
39. ]
通过db.system.indexes.find()能够返回当前数据库中的所有索引
1. >
db.system.indexes.find()
2.
3. { "name" : "_id_", "ns" :
"things.things", "key" : { "_id" : 1 }, "v" : 0 }
4.
5. { "_id" :
ObjectId("4e244382cac1e3490b9033d0"), "ns" : "things.things", "key" :{ "j" : 1
}, "name" : "j_1", "v" : 0 }
rails 如何从mongodb 中取出某索引值的最大值
索引通常能够极大的提高查询的效率。在系统中使用查询时,应该考虑建立相关的索引。在MongoDB中创建索引相对比较容易。
MongoDB中的索引在概念上和大多数关系型数据库如MySQL是一样的。当你在某种情况下需要在MySQL中建立索引,这样的情景同样适合于MongoDB。
基本操作
索引是一种数据结构,他搜集一个集合中文档特定字段的值。MongoDB的查询优化器能够使用这种数据结构来快速的对集合(collection)中的文档(collection)进行寻找和排序.准确来说,这些索引是通过B-Tree索引来实现的。
在命令行中,可以通过调用ensureIndex()函数来建立索引,该函数指定一个到多个需要索引的字段。沿用在前面的随笔中的例子,我们再things集合中的j字段上建立索引:
1. >
db.things.ensureIndex({j:1})
EnsureIndex()函数自是在索引不存在的情况下才会创建。
一旦集合在某一个字段上建立索引后,对该字段的随机查询的访问速度会很快。如果没有索引,MongoDB会在遍历所有的键值对,然后去对应检查相关的字段。
1. >
db.things.find({j:2}); //在建立了索引的字段上查询,速度快
2.
3. { "_id" :
ObjectId("4e24433dcac1e3490b9033be"), "x" : 4, "j" : 2 }
4.
5. >
db.things.find({x:3});//在未建立索引的字段上查询,需要逐个字段匹配,速度慢
6.
7. { "_id" :
ObjectId("4e244315cac1e3490b9033bc"), "x" : 3
}
通过在命令行中输入getIndexs()能够查看当前集合中的所有索引。
1. >
db.things.getIndexes()
2.
3. [
4.
5. {
6.
7. "name"
: "_id_",
8.
9. "ns" : "things.things",
10.
11. "key" :
{
12.
13. "_id" : 1
14.
15. },
16.
17. "v" :
0
18.
19. },
20.
21. {
22.
23. "_id" :
ObjectId("4e244382cac1e3490b9033d0
24.
25. "ns" :
"things.things",
26.
27. "key" : {
28.
29. "j" :
1
30.
31. },
32.
33. "name" : "j_1",
34.
35. "v" :
0
36.
37. }
38.
39. ]
通过db.system.indexes.find()能够返回当前数据库中的所有索引
1. >
db.system.indexes.find()
2.
3. { "name" : "_id_", "ns" :
"things.things", "key" : { "_id" : 1 }, "v" : 0 }
4.
5. { "_id" :
ObjectId("4e244382cac1e3490b9033d0"), "ns" : "things.things", "key" :{ "j" : 1
}, "name" : "j_1", "v" : 0 }
谁能说说mangodb 和 hbase的区别
1.Mongodb bson文档型数据库,整个数据都存在磁盘中,hbase是列式数据库,集群部署时每个familycolumn保存在单独的hdfs文件中。
2.Mongodb 主键是“_id”,主键上面可以不建索引,记录插入的顺序和存放的顺序一样,hbase的主键就是row key,可以是任意字符串(最大长度是 64KB,实际应用中长度一般为 10-100bytes),在hbase内部,row key保存为字节数组。存储时,数据按照Row key的字典序(byte order)排序存储。设计key时,要充分排序存储这个特性,将经常一起读取的行存储放到一起。
字典序对int排序的结果是1,10,100,11,12,13,14,15,16,17,18,19,2,20,21,…,9,91,92,93,94,95,96,97,98,99。要保持整形的自然序,行键必须用0作左填充。
3.Mongodb支持二级索引,而hbase本身不支持二级索引
4.Mongodb支持集合查找,正则查找,范围查找,支持skip和limit等等,是最像mysql的nosql数据库,而hbase只支持三种查找:通过单个row key访问,通过row key的range,全表扫描
5.mongodb的update是update-in-place,也就是原地更新,除非原地容纳不下更新后的数据记录。而hbase的修改和添加都是同一个命令:put,如果put传入的row key已经存在就更新原记录,实际上hbase内部也不是更新,它只是将这一份数据已不同的版本保存下来而已,hbase默认的保存版本的历史数量是3。
6.mongodb的delete会将该行的数据标示为已删除,因为mongodb在删除记录时并不是真把记录从内存或文件中remove,而是将该删除记录数据置空(写0或特殊数字加以标识)同时将该记录所在地址放到一个list列表“释放列表”中,这样做的好就是就是如果有用户要执行插入记录操作时,mongodb会首先从该“释放列表”中获取size合适的“已删除记录”地址返回,这种方法会提升性能(避免了malloc内存操作),同时mongodb也使用了bucket size数组来定义多个大小size不同的列表,用于将要删除的记录根据其size大小放到合适的“释放列表”中。Hbase的delete是先新建一个tombstonemarkers,然后读的时候会和tombstonemarkers做merge,在 发生major compaction时delete的数据记录才会真真删除。
7.mongodb和hbase都支持maprece,不过mongodb的maprece支持不够强大,如果没有使用mongodb分片,maprece实际上不是并行执行的
8.mongodb支持shard分片,hbase根据row key自动负载均衡,这里shard key和row key的选取尽量用非递增的字段,尽量用分布均衡的字段,因为分片都是根据范围来选择对应的存取server的,如果用递增字段很容易热点server的产生,由于是根据key的范围来自动分片的,如果key分布不均衡就会导致有些key根本就没法切分,从而产生负载不均衡。
9.mongodb的读效率比写高,hbase默认适合写多读少的情况,可以通过hfile.block.cache.size配置,该配置storefile的读缓存占用Heap的大小百分比,0.2表示20%。该值直接影响数据读的性能。如果写比读少很多,开到0.4-0.5也没问题。如果读写较均衡,0.3左右。如果写比读多,果断默认0.2吧。设置这个值的时候,你同时要参考hbase.regionserver.global.memstore.upperLimit,该值是memstore占heap的最大百分比,两个参数一个影响读,一个影响写。如果两值加起来超过80-90%,会有OOM的风险,谨慎设置。
10.hbase采用的LSM思想(Log-Structured Merge-Tree),就是将对数据的更改hold在内存中,达到指定的threadhold后将该批更改merge后批量写入到磁盘,这样将单个写变成了批量写,大大提高了写入速度,不过这样的话读的时候就费劲了,需要merge disk上的数据和memory中的修改数据,这显然降低了读的性能。mongodb采用的是mapfile+Journal思想,如果记录不在内存,先加载到内存,然后在内存中更改后记录日志,然后隔一段时间批量的写入data文件,这样对内存的要求较高,至少需要容纳下热点数据和索引。
谁能说说mangodb 和 hbase的区别
1.Mongodb bson文档型数据库,整个数据都存在磁盘中,hbase是列式数据库,集群部署时每个familycolumn保存在单独的hdfs文件中。
2.Mongodb 主键是“_id”,主键上面可以不建索引,记录插入的顺序和存放的顺序一样,hbase的主键就是row key,可以是任意字符串(最大长度是 64KB,实际应用中长度一般为 10-100bytes),在hbase内部,row key保存为字节数组。存储时,数据按照Row key的字典序(byte order)排序存储。设计key时,要充分排序存储这个特性,将经常一起读取的行存储放到一起。
字典序对int排序的结果是1,10,100,11,12,13,14,15,16,17,18,19,2,20,21,…,9,91,92,93,94,95,96,97,98,99。要保持整形的自然序,行键必须用0作左填充。
3.Mongodb支持二级索引,而hbase本身不支持二级索引
4.Mongodb支持集合查找,正则查找,范围查找,支持skip和limit等等,是最像mysql的nosql数据库,而hbase只支持三种查找:通过单个row key访问,通过row key的range,全表扫描
5.mongodb的update是update-in-place,也就是原地更新,除非原地容纳不下更新后的数据记录。而hbase的修改和添加都是同一个命令:put,如果put传入的row key已经存在就更新原记录,实际上hbase内部也不是更新,它只是将这一份数据已不同的版本保存下来而已,hbase默认的保存版本的历史数量是3。
6.mongodb的delete会将该行的数据标示为已删除,因为mongodb在删除记录时并不是真把记录从内存或文件中remove,而是将该删除记录数据置空(写0或特殊数字加以标识)同时将该记录所在地址放到一个list列表“释放列表”中,这样做的好就是就是如果有用户要执行插入记录操作时,mongodb会首先从该“释放列表”中获取size合适的“已删除记录”地址返回,这种方法会提升性能(避免了malloc内存操作),同时mongodb也使用了bucket size数组来定义多个大小size不同的列表,用于将要删除的记录根据其size大小放到合适的“释放列表”中。Hbase的delete是先新建一个tombstonemarkers,然后读的时候会和tombstonemarkers做merge,在 发生major compaction时delete的数据记录才会真真删除。
7.mongodb和hbase都支持maprece,不过mongodb的maprece支持不够强大,如果没有使用mongodb分片,maprece实际上不是并行执行的
8.mongodb支持shard分片,hbase根据row key自动负载均衡,这里shard key和row key的选取尽量用非递增的字段,尽量用分布均衡的字段,因为分片都是根据范围来选择对应的存取server的,如果用递增字段很容易热点server的产生,由于是根据key的范围来自动分片的,如果key分布不均衡就会导致有些key根本就没法切分,从而产生负载不均衡。
9.mongodb的读效率比写高,hbase默认适合写多读少的情况,可以通过hfile.block.cache.size配置,该配置storefile的读缓存占用Heap的大小百分比,0.2表示20%。该值直接影响数据读的性能。如果写比读少很多,开到0.4-0.5也没问题。如果读写较均衡,0.3左右。如果写比读多,果断默认0.2吧。设置这个值的时候,你同时要参考hbase.regionserver.global.memstore.upperLimit,该值是memstore占heap的最大百分比,两个参数一个影响读,一个影响写。如果两值加起来超过80-90%,会有OOM的风险,谨慎设置。
10.hbase采用的LSM思想(Log-Structured Merge-Tree),就是将对数据的更改hold在内存中,达到指定的threadhold后将该批更改merge后批量写入到磁盘,这样将单个写变成了批量写,大大提高了写入速度,不过这样的话读的时候就费劲了,需要merge disk上的数据和memory中的修改数据,这显然降低了读的性能。mongodb采用的是mapfile+Journal思想,如果记录不在内存,先加载到内存,然后在内存中更改后记录日志,然后隔一段时间批量的写入data文件,这样对内存的要求较高,至少需要容纳下热点数据和索引。
mongodb新插入数据时需要重新建索引吗
1. 索引的创建
mongodb采用ensureIndex来创建索引,如:
db.user.ensureIndex({"name":1})
表示在user集合的name键创建一个索引,这里的1表示索引创建的方向,可以取值为1和-1
在这里面,我们没有给索引取名字,mongodb会为我们取一个默认的名字,规则为keyname1_dir1_keyname2_dir2...keynameN_dirN
keyname表示键名,dir表示索引的方向,例如,上面的例子我们创建的索引名字就是name_1
索引还可以创建在多个键上,也就是联合索引,如:
> db.user.ensureIndex({"name":1,"age":1})
这样就创建了name和age的联合索引
除了让mongodb默认索引的名字外,我们还可以去一个方便记的名字,方法就是为ensureIndex指定name的值,如:
> db.user.ensureIndex({"name":1},{"name":"IX_name"})
这样,我们创建的索引的名字就叫IX_name了
2. 唯一索引
与RDB类似,我们也可以定义唯一索引,方法就是指定unique键位true:
>db.user.ensureIndex({"name":1},{"unique":true})
3.查看我们建立的索引
索引的信息存在每个数据库的system.indexes集合里面,对这个集合只能有ensureIndex和dropIndexes进行修改,不能手动插入或修改集合。
通过> db.system.indexes.find()可以找到数据库中多有的索引:
> db.system.indexes.find()
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.entities", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.blog", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.authors", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.papers", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.analytics", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.user", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.food", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.user.info", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.userinfo", "name" : "_id_" }
{ "v" : 1, "key" : { "name" : 1 }, "ns" : "test.user", "name" : "IX_name" }
4.删除索引
如果索引没有用了,可以使用dropIndexes将其删掉:
> db.runCommand({"dropIndexes":"user","index":"IX_name"})
{ "nIndexesWas" : 2, "ok" : 1 }
ok表示删除成功
mongodb新插入数据时需要重新建索引吗
1. 索引的创建
mongodb采用ensureIndex来创建索引,如:
db.user.ensureIndex({"name":1})
表示在user集合的name键创建一个索引,这里的1表示索引创建的方向,可以取值为1和-1
在这里面,我们没有给索引取名字,mongodb会为我们取一个默认的名字,规则为keyname1_dir1_keyname2_dir2...keynameN_dirN
keyname表示键名,dir表示索引的方向,例如,上面的例子我们创建的索引名字就是name_1
索引还可以创建在多个键上,也就是联合索引,如:
> db.user.ensureIndex({"name":1,"age":1})
这样就创建了name和age的联合索引
除了让mongodb默认索引的名字外,我们还可以去一个方便记的名字,方法就是为ensureIndex指定name的值,如:
> db.user.ensureIndex({"name":1},{"name":"IX_name"})
这样,我们创建的索引的名字就叫IX_name了
2. 唯一索引
与RDB类似,我们也可以定义唯一索引,方法就是指定unique键位true:
>db.user.ensureIndex({"name":1},{"unique":true})
3.查看我们建立的索引
索引的信息存在每个数据库的system.indexes集合里面,对这个集合只能有ensureIndex和dropIndexes进行修改,不能手动插入或修改集合。
通过> db.system.indexes.find()可以找到数据库中多有的索引:
> db.system.indexes.find()
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.entities", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.blog", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.authors", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.papers", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.analytics", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.user", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.food", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.user.info", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.userinfo", "name" : "_id_" }
{ "v" : 1, "key" : { "name" : 1 }, "ns" : "test.user", "name" : "IX_name" }
4.删除索引
如果索引没有用了,可以使用dropIndexes将其删掉:
> db.runCommand({"dropIndexes":"user","index":"IX_name"})
{ "nIndexesWas" : 2, "ok" : 1 }
ok表示删除成功
为什么有关MongoDB采用B树索引,以及Mysql B+树做索引
事实上,在MySQL数据库中,诸多存储引擎使用的是B+树,即便其名字看上去是BTREE。
4.1 innodb的索引机制
先以innodb存储引擎为例,说明innodb引擎是如何利用B+树建立索引的
首先创建一张表:zodiac,并插入一些数据
对于innodb来说,只有一个数据文件,这个数据文件本身就是用B+树形式组织,B+树每个节点的关键字就是表的主键,因此innode的数据文件本身就是主索引文件,如下图所示,主索引中的叶子页(leaf page)包含了数据记录,但非叶子节点只包含了主键,术语“聚簇”表示数据行和相邻的键值紧凑地存储在一起,因此这种索引被称为聚簇索引,或聚集索引。
这种索引方式,可以提高数据访问的速度,因为索引和数据是保存在同一棵B树之中,从聚簇索引中获取数据通常比在非聚簇索引中要来得快。
所以可以说,innodb的数据文件是依靠主键组织起来的,这也就是为什么innodb引擎下创建的表,必须指定主键的原因,如果没有显式指定主键,innodb引擎仍然会对该表隐式地定义一个主键作为聚簇索引。
同样innodb的辅助索引,如下图所示,假设这些字符是按照生肖的顺序排列的(其实我也不知道具体怎么实现,不要在意这些细节,就是举个例子),其叶子节点中也包含了记录的主键,因此innodb引擎在查询辅助索引的时候会查询两次,首先通过辅助索引得到主键值,然后再查询主索引,略微有点啰嗦