MongoDB-基础知识学习(一)

概述

最近mongodb在互联网的活跃度直线上升,并且我们公司也使用了mongoDB 3.6 作为生产重要的数据库,我们项目组要监控mongodb的op.log日志,在此整理以前学习的知识,为以后备份学习使用。

定义和特性

MongoDB是一款为web应用程序和互联网基础设施设计的数据库管理系统。而且是NoSQL类型的数据库。

1),mongoDB提出的是文档、集合的概念

它使用BSON(类JSON)作为其数据结构模型,其结构是面向对象而不是二维表,例如:

 

{
    "_id" : ObjectId("5cf60b44e574a35d02c1ca80"),
    "host" : "rhel67129230"
}

 

  

SQL类型的数据库是正规化的,可以通过主键或者外键的约束保证数据的完整性和唯一性,所以SQL类型的数据库常用于对数据完整性较高的系统。MongoDB在这一方面是不如SQL类型的数据库,且MongoDB没有固定的schema, 正因为mongoDB少了这些特性,数据库结构存贮更灵活,存储速度更快。

2),易伸缩,自动故障转移

易伸缩是指提供了分片的能力,能对数据集进行分片,数据的存储压力分摊给多台服务器。自动故障转移是副本集的概念,MongoDB能检测主节点是否存活,当失活时能自动提升从节点升级到主节点,达到故障转移的能力。

3),即时查询能力

MongoDB保留了关系型数据库即时查询的能力,保留了索引的功能(底层是基于 B TREE),这一点汲取了关系型数据库的优点。

4),速度和持久性

MongoDB的驱动实现一个写入的语义 fire and forget ,即通过驱动调入写入时,可以立即得到返回得到成功的结果(即使是报错),这样写入的速度更加快,当然会有一定的不安全性,完全依赖网络。

MongoDB提供了Journaling日志的概念,实际上是mysql类似的bin-log日志,当需要插入的时候会先往日志里面写入记录,在完成实际的数据操作,这样如果中途出现问题可以修复。

 

 数据库语法

查找语法

 

db.users.find()
db.users.count()

 

  

 

更新语法

db.users.update({username:"smith"},{$set:{country:"Canada"}})
//把用户名为smith的用户的国家改成Canada

db.users.update({username:"smith"},{$unset:{country:1}})
//把用户名为smith的用户的国家字段给移除

db.users.update({username:"jones"},{$set:{favorites:{movies:["casablance","rocky"]}}})
//这里主要体现多值修改,在favorties字段中添加多个值

db.users.update({"favorites.movies":"casablance"},{$addToSet:{favorites.movies:"the maltese"}},false,true)
//多项更新

  

删除语法

db.foo.remove() //删除所有数据
db.foo.remove({favorties.cities:"cheyene"}) //根据条件进行删除
db.drop() //删除整个集合

  

索引相关语法

db.numbers.ensureIndex({num:1})
//创建一个升序索引
db.numbers.getIndexes()
//获取全部索引

 

基本管理语法

show dbs
//查询所有数据库
show collections
//显示所有表
db.stats()
//显示数据库状态信息
db.numbers.stats()
//显示集合表状态信息
db.shutdownServer()
//停止数据库
db.help()
//获取数据库操作命令
db.foo.help()
//获取表操作命令
tab 键 //能自动帮我们补全命令

 

SCHEMA设计原则

在关于schema 的设计中要注意一些原则,比如:

  • 不能创建没用的索引

  • 不能在同一个字段中存不同的类型

  • 不能把多类实体都放在一个集合里 不能创建体积大、嵌套深的文档

  • 不能过多的创建集合,集合、索引、数据库的命名空间都是有限的

  • 不能创建无法分片的集合

 

关注mongodb里面的一些细节

1,关于数据库的概念

数据库是集合的逻辑和分组,mongodb没有创建数据库的方法,只有再插入集合时,数据库才开始建立。创建数据库后会在磁盘分配一组数据问价,所有集合、索引和数据库的其他元数据都会保存在这些文件中,查阅数据库磁盘状态可以使用命令: db.stats()

2,关注集合的概念

集合是结构上或者概念上相似的文档的容器,集合的名称可以包含数字、字母或符号,但是必须以字母或者数字开头。限定集合名不能超过128字符。

3,关注文档的概念

其次是键值,在mongodb里面都是utf-8类型。数字类型包括double,int,lon。日期类型都是UTC格式,所以在mongodb里面的时间都是比北京时间慢8小时。整个文档大小都会限定在16m以内,因为这样可以限制创建难看的数据类型,而且小文档可以提升性能。

4,索引的概念

索引包含:单建索引,复合索引,唯一性索引,稀疏索引。

如果数据集很大的时候,构建索引将会花费很多时间,且会影响程序进程,可通过  db.currentOp() 查看索引的构建时间。

当执行大规模删除的时候,可使用  db.values.reIndex() 对索引进行压缩和重建。

5,识别慢查询

查阅慢查询日志

grep -E '([0-9])+ms' mongod.log //使用grep 命令 识别命令信息

db.setProfillingLevel(2) //使用解刨器,将记录每次的读写到日志

db.setProfillingLevel(1) //只记录慢(100ms)操作

 

分析慢查询

db.values.find({}).sort({close:-1}).limit(1).explain()

 

  • scanOrder 字段表明没有使用索引

  • cursor当没有索引时,用的是BasicCursor,当使用索引时使用的是BtreeCursor

  • n 表示需要返回的结果集

  • nscanned表示需要遍历的文档数 indexBounds 表示索引边界

 

MONGODB副本集

 

实际上MongoDB对副本集的操作跟mysql主从操作是差不多的,先看一下mysql的主从数据流动过程

主binlog -> 从relay.log -> 从bin.log -> 从数据库

而MongoDB主要依赖的日志文件是oplog

主oplog -> 从oplog

写操作先被记录下来,添加到主节点的oplog里。与此同时,所有从结点复制oplog。首先,查看自己oplog里最后一条的时间戳;其次,查询主节点oplog里所有大于此时间戳的条目;最后,把那些条目添加到自己的oplog里并应用到自己的库里。从节点使用长轮询立即应用来自主结点oplog的新条目。

当遇到以下情况,从节点会停止复制

  • 如果从节点在主节点的oplog里找不到它所同步的点,那么会永久停止复制

  • 一旦某个从节点没能 在主节点的oplog里找到它已经同步的点,就无法再保证这个从结点的完美副本

local数据库保存了所有副本集元素据和oplog日志

  • replset.minvalid 包含指定副本集成员的初始化同步信息

  • system.replset 保存在副本集配置文档

  • system.indexes 标准索引说明容器

  • me slaves 主要用于写关注

可以使用以下命令查看复制情况

db.oplog.rs.findOne()
  • ts 保存了该条目的BSON时间戳

  • t 是从纪元开始的描述

  • i是计数器

  • op 表示操作码

  • ns 标明了有关的命名空间

 

分片

分片是指将数据库进行拆分,将其分散到不同的机器上的过程。将数据分散到不同的服务器上,不需要功能强大的服务器就可以存储更多的数据和处理更大的负载。基本思想就是将集合切成小块,这些快分散到若干的片里面,每个片只负责数据的一部分,最后通过一个均衡器来对各个分片进行均衡,主要是通过一个名为mongos的路由进程进行操作。大部分分片的使用场景都是解决磁盘空间问题,对于写入有可能变差,查询尽量避免分片查询,使用分片的动机是:

1,机器的磁盘不够用,使用分片解决磁盘问题。

2,单个mongod已经不能满足写数据的性能要求,通过分片可以让写的压力分散到各个机器上面。

3,想把大量数据放到内存中,提升性能。

分片的组件

分片:每个分片都是一个副本集。

分片的核心操作

分片的一个集合:分片是根据一个属性的范围进行划分的,mongodb使用所谓的分片键让每个文档在这些范围里面找到自己的位置。

快:是位于一个分片中一段连续的分片建范围,可以理解为若干个快组成分片,分片组成mongodb的所有数据。

拆分和迁移

块的拆分:初始化只有一块,快达到最大尺寸64m或者100000个文档就会触发块的拆分。把原来的范围一分为二,这样就有了2块,每个块都有相同数量的文档。

迁移:当分片的数据大小不一的时候就会产生迁移的操作,分片集群是通过分片中移动块来实现均衡,

sh.help() //查看分片相关帮助
sh.addShard() //添加分片
db,getSiblingDB("config").shards.find() //查看分片列表
sh.status() //分片详情
sh.enableSharding("cloud-docs") //开启一个数据库上的分片
db.getSiblingDB("config").databases,find() //查看数据库列表
sh.shardCollection("cloud-docs.spreadsheets",{username:1,_id:1}) //使用一个分片键定义一个分片集合spreadsheets,根据用户名进行切分
sh.getSiiblingDB("config").collections.findOne() //查看集合列表
db.chunks.count() //查看块的个数
db.chunks.findOne() //查看块的信息
db.changelog.count(}what:"split"|) //查看块切分日志
db.changelog.find({what:"moveChunk.commit"}).count() //查看日志迁移记录

 

 

你可能感兴趣的:(MongoDB-基础知识学习(一))