①MongoDB基本知识①

MongDB属于非关系型数据库一派,没有固定的数据格式存储,是一个具备高性能、高拓展的文档型数据库,数据以BSON(JSON的二进制)的格式存储。

特点:

  1. 基于对象模型,关系简单。没有外键的约束,也没有强连接表的关系,适用于对需求不确定的系统开发。
  2. 反范式、无关联的组织结构极大的加快了查询的速度。
  3. 同一个集合中对象包含的字段可以不同,能根据需求快速响应,属于半结构化数据,对开发十分友好便捷。
  4. MongoDB支持高可用,实现一主多从,主节点宕机了,从节点会经过筛选承担主节点的位置。
  5. MongoDB支持可拓展,对于数据可进行分片处理,对于应用透明。
  6. 提供JS形式的API方法,操作简便

一、MongoDB基本概念(同关系型数据库对比)

1.专有名词

关系型数据库 MongoDB
字段(field) 字段(field)
行(row) 文档(document)
表(table) 集合(collection)
数据库(database) 数据库(database)
主键(自定义 primary key) 主键(_id,自动生成 )
索引(index) 索引(index)
表连接(left join) 聚合操作(管道))

2.JSON vs BSON

JSON BSON
存在形式 基于文本形式 基于二进制编/解码
遍历速度 较慢
数据类型 6种 丰富

JSON支持的六种基础类型:

	string: 字符串 
	number : 数值 
	object: JS的对象形式,用{key:value}表示 
	可嵌套 array: 数组,JS的表示方式[value] 
	布尔类型  true/false: 
	null: 空值
2.1 BSON数据格式


官方地址

可以利用BSON的数据格式type进行查询匹配,例如:db.collection.find({"title" : {$type : "string"}})

部分数据类型讲解

2.1.1 时间类型
	db.collection.insert([{data1:Date()},{data2:new Date()},{data3:ISODate()}])
	ISODate() = new Date(),得到的是UTC的时间,Date()得到的是本地时间
2.1.2 ObjectId生成器

所有的文档都有一个_id字段,且是唯一的,相当于主键。_id字段的值采用16进制编码形式,共12个字节。是通过ObjectId生成器生成的,且具有一定的规则来保证唯一。

ObjectId被定义为3个部分: 4字节表示Unix时间戳(秒)。 5字节表示随机数(机器号+进程号唯一)。 3字节表示计数器(初始化时随机)。

二、MongoDB命令基本使用

1、用户操作

2、集合操作

3、文档操作

三、固定集合(capped collection)

固定集合,从字面意思就可以知道,长度是固定的,适用于短时间使用的数据存储。遵循先进先出的原则,所以当空间已满时,会将最先进的文档,进行取代。

db.createCollection("logs",{capped:true,size:4096,max:10})
capped: true 指定为固定集合,size指定固定集合存储空间的大小

优势:

  1. 遵循先进先出原则,底层根据顺序IO操作,读写性能高

缺点:

  1. 无法动态修改存储的上限

  2. 无法删除已有的数据

四、WiredTiger(读写模型存储引擎)

引入WiredTiger,对于MongoDB就是如虎添翼,加快了读写的效率,也进一步保障数据的不丢失。

读取依赖于WiredTiger的内存缓存,主要原理如下:

  1. 数据库发起读IO操作,操作系统将磁盘数据经过调度加载在页面缓存区中。
  2. 存储引擎读取页面的数据,通过加压缩的方式存储在内存缓存区中。
  3. 在存储引擎内存中进行匹配,匹配成功后返回结果。

写操作(减少磁盘IO,提高速率): 当数据发生写入时,MongoDB并不会立即持久化到磁盘上,而是先在内存中记录这些变更,之后通过CheckPoint机制将变化的数据写入磁盘。

主要基于两部分保障数据的不丢失

  1. 基于快照(CheckPoint): 每60秒一次进行保存
  2. 基于日志(Journal): 保存所有的写操作,以便快照失效能保存数据

另外MongoDB为了尽可能保证业务查询的"热数据"能快速被访问,其内部缓存的默认大小达到了内存的一半

五、 mongoDB索引讲解

索引的建立是为了更快速的获取到查询的结果,MongoDB的索引数据结构选取的是B+tree。

索引的分类有如下几种情况:

  1. 按照索引的字段数量进行分类: 单键索引、组合索引(复合索引)
  2. 按照索引的字段是否为主键进行分类: 主键索引、非主键索引
  3. 按照索引节点中物理记录来区分,聚簇索引(包含指针和数据)、非聚簇索引(只有指针)
  4. 索引特性: 唯一索引、地理位置索引、ttl索引、文本索引、稀释索引等。

1.索引操作命令

索引创建操作命令的options参数有

1.1 普通索引
	db.collection.createIndex(keys, options) 创建索引命令
	其中key,指定1为升序,指定-1为降序
	# 创建索引后台执行
	db.collection.createIndex({open: 1, close: 1}, {background: true})
	#创建唯一索引,在options位置上添加unique:true即可
	db.collection.createIndex({_id: 1},{unique: true})
	//查看当前集合的所有索引
	db.collection.getIndexes()
	//查看当前集合的所有索引健
	db.collection.getIndexKeys()
	//查看索引所占空间
	db.collection.totalIndexSize([is_detail])
	//删除索引
	db.collection.dropIndex('索引名称')
	//删除集合下所有索引
	db.collection.dropIndexes();
1.2 复合索引
	创建复合索引(索引包含多个字段值)
	db.collection.createIndex({type:1,favCount:1})
1.3 多键索引(与复合索引不同)
	例如 ratings: [1,2,3]是一个数组,包含了多个值,在此基础上建立索引称为多键索引
	db.collection.createIndex({rating:1})
	在范围上 多键索引<= 复合索引
1.4 地理位置索引
// 创建一个2dsphere索引
db.collection.createIndex({location : "2dsphere"})
// 查询附近10000米商家信息
db.restaurant.find( { 
    location:{ 
        $near :{
            $geometry :{ 
                type : "Point" ,
                coordinates : [  -73.88, 40.78 ] 
            } ,
            $maxDistance:10000 
        } 
    } 
} )

参数说明

$near查询操作符,用于实现附近商家的检索,返回数据结果会按距离排序。$geometry操作符用于指定一个GeoJSON格式的地理空间对象,type=Point表示地理坐标点,coordinates则是用户当前所在的经纬度位置;$maxDistance限定了最大距离,单位是米。

1.5 全文索引

全文索引能实现简易的分词检索,选定索引字段后,赋值为text即为全文索引。

#创建全文索引
db.collection.createIndex( { comment: "text" } )
// 通过$text操作符来查寻数据中所有包含"coffee","shop","java"列表中任何词语的商店
db.colletion.find({$text: {$search: "java coffee shop"}})
1.6 Hash索引

哈希索引使用哈希来创建索引,能实现精确匹配,但不支持范围索引和多键Hash。

db.collection.createIndex({name: "hashed"})
1.7通配符索引

对于索引建立的字段不确定时,可以使用通配符进行索引,用$**的方式进行匹配。

db.collection.insert([
    {
      "product_name" : "Spy Coat",
      "product_attributes" : {
        "material" : [ "Tweed", "Wool", "Leather" ],
        "size" : {
          "length" : 72,
          "units" : "inches"
        }
      }
    },
    {
      "product_name" : "Spy Pen",
      "product_attributes" : {
         "colors" : [ "Blue", "Black" ],
         "secret_feature" : {
           "name" : "laser",
           "power" : "1000",
           "units" : "watts",
         }
      }
    },
    {
      "product_name" : "Spy Book"
    }
])
# 创建通配符索引
db.collection.createIndex( { "product_attributes.$**" : 1 } )
# 通配符索引的使用
db.collection.find( { "product_attributes.size.length" : { $gt : 60 } } )
db.collection.find( { "product_attributes.material" : "Leather" } )
db.collection.find( { "product_attributes.secret_feature.name" : "laser" 

特性:

1.通配符索引不适用于其他特性的索引

2.通配符索引不能用于查询不存在字段的文档

3.通配符索引不能支持精确的对象或数据精准匹配

1.8 唯一索引

创建索引时提高unique:true的配置即可

db.collection.createIndex({title:1,type:1},{unique: true})
1.9 部分索引

部分索引也可以叫过滤索引,就是将索引进行条件过滤,符合条件的索引可以进行部分索引。

# 创建过滤索引
db.collection.createIndex(
  { cuisine: 1, name: 1 }, # 索引字段
  { partialFilterExpression: { rating: { $gt: 5 } } } 
)
#使用过滤索引
#符合条件,使用索引
db.collection.find( { cuisine: "Italian", rating: { $gte: 8 } } )
#不符合条件,不能使用索引
db.collection.find( { cuisine: "Italian" } )

如果同时指定了partialFilterExpression和唯一约束,那么唯一约束只适用于满足筛选器表达式的文档

1.10 稀释索引

稀疏索引对存在索引字段的文档进行索引,不存在该字段的会过滤(对存在字段的文档进行索引(包括字段值为null的文档))。

#创建稀释索引(在选项位置添加sparse: true即可)
db.collection.createIndex( { "name": 1 }, { sparse: true } )
#可以和唯一索引一起使用
db.collection.createIndex({"name": 1},{sparse: true,unique:true})
#二者结合可以防止集合中存在字段值重复的文档,
#但允许不包含此索引字段的文档插入(满足稀释条件的唯一,不满足不唯一)。
1.11 TTL索引

对于随着时间推移,不再使用的数据要进行清理,以降低内存的消耗。我们要对这些数据进行老化处理,就需要给数据指定一个清理时间,常规解决方法有两个,一个是为每个数据指定一个时间戳定时清理,一个是将数据进行存表分类,之后对该表进行定时清理。而MongoDB提供给TTL索引,我们只需要声明在一个日期类型的字段中,TTL 索引是特殊的单字段索引。

# TTL索引标识(expireAfterSeconds: 3600 ) 指定expireAfterSeconds
db.collection.createIndex( { "lastModifiedDate": 1 }, { expireAfterSeconds: 3600 } )

#可以进行更改过期时间
db.runCommand({collMod:"集合名称",index:{keyPattern:{createdAt:1},expireAfterSeconds:600}})
1.12 隐藏索引

隐藏索引的好处就是对部分带有负面影响的索引进行隐藏

#创建隐藏索引
db.collection.createIndex({ borough: 1 },{ hidden: true });
# 现有隐藏索引
db.collection.hideIndex( { borough: 1} );
#取消隐藏索引
db.scores.unhideIndex( { userid: 1} )

2.索引执行情况

在查询的过程中,我们需要去清理我们是否使用了索引以及索引起到了什么样的效果,这个时候我们就需要通过explain()去获取数据扫描的情况。

verbose参数如下:

db.collection.find().explain(<verbose>)

stage的状态可以判断出是否使用了索引进行扫描

使用的时候尽量不要出现以下的stage:

  1. COLLSCAN(全表扫描)
  2. SORT(使用sort但是无index)
  3. 不合理的SKIP
  4. SUBPLA(未用到index的$or)
  5. COUNTSCAN(不使用index进行count)
相关推荐
好记忆不如烂笔头abc9 分钟前
统计信息的导出导入
数据库
Casual_Lei33 分钟前
Neo4j
数据库·oracle·neo4j
IT枫斗者41 分钟前
集合工具类
java·linux·数据库·windows·算法·microsoft
大厂小码哥1 小时前
图解Redis 01 | 初识Redis
数据库·redis·缓存
咚咚?2 小时前
麒麟操作系统 MySQL 主从搭建
数据库·mysql
爬山算法3 小时前
Oracle(130)如何启动和关闭Oracle数据库?
数据库·oracle
天荒地老笑话么4 小时前
MySQL——数据库的高级操作(三)权限管理(1)MySQL 的权限
数据库·mysql
天荒地老笑话么8 小时前
MySQL——数据库的高级操作(二)用户管理(1)uer表
数据库·mysql
GG编程8 小时前
Mysql 索引
数据库·mysql
Python私教8 小时前
Go语言现代web开发13 方法和接口
前端·数据库·golang