①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)
相关推荐
woshilys20 分钟前
sql server 查询对象的修改时间
运维·数据库·sqlserver
Hacker_LaoYi21 分钟前
SQL注入的那些面试题总结
数据库·sql
建投数据1 小时前
建投数据与腾讯云数据库TDSQL完成产品兼容性互认证
数据库·腾讯云
Hacker_LaoYi2 小时前
【渗透技术总结】SQL手工注入总结
数据库·sql
岁月变迁呀2 小时前
Redis梳理
数据库·redis·缓存
独行soc2 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍06-基于子查询的SQL注入(Subquery-Based SQL Injection)
数据库·sql·安全·web安全·漏洞挖掘·hw
你的微笑,乱了夏天3 小时前
linux centos 7 安装 mongodb7
数据库·mongodb
工业甲酰苯胺3 小时前
分布式系统架构:服务容错
数据库·架构
独行soc4 小时前
#渗透测试#漏洞挖掘#红蓝攻防#护网#sql注入介绍08-基于时间延迟的SQL注入(Time-Based SQL Injection)
数据库·sql·安全·渗透测试·漏洞挖掘
White_Mountain4 小时前
在Ubuntu中配置mysql,并允许外部访问数据库
数据库·mysql·ubuntu