给出两个简单的实验
实验一 ACID 操作
(1)建立一个三个节点的副本集。
(2)自行建立一个集合,一次性插入多条文档记录,要求大多数节点都成功插入,
才能返回操作成功信息。
(3)对其中一条文档进行原子修改操作,要求一个节点修改完成,就可以返回操作
功信息。
(4)给出实验过程和实验结果。
1)创建三个节点的副本集
创建MongoDB目录结构如下,
MongoDB/
├── data/
│ ├── db/
│ │
│ │
│ │
│ └── log/
│ └── mongod.log
├── bin/
MongoDB1/
├── data/
│ ├── db/
│ │
│ │
│ │
│ └── log/
│ └── mongod.log
├── bin/
│
MongoDB2/
├── data/
│ ├── db/
│ │
│ │
│ │
│ └── log/
│ └── mongod.log
├── bin/
然后打开命令行窗口,来启动副本集
分三个命令行窗口运行,命令如下
mongod -port 27018 -dbpath "E:\MongoDB1\data\db" -logpath "E:\MongoDB1\data\log\mongod.log" -replSet rs0
mongod -port 27017 -dbpath "E:\MongoDB\data\db" -logpath "E:\MongoDB\data\log\mongod.log" -replSet rs0
mongod -port 27019 -dbpath "E:\MongoDB2\data\db" -logpath "E:\MongoDB2\data\log\mongod.log" -replSet rs0
然后进入mongodbshell来对副本集进行初始化,以管理员权限打开mongosh.exe
默认27017端口
先选择admin管理员
use admin
再设置副本集
config = {_id:"rs0",members:[
{_id:0,host:"localhost:27017","priority":3},
{_id:1,host:"localhost:27018","priority":2},
{_id:2,host:"localhost:27019","priority":1}]}
再输入以下命令,对副本集进行初始化
rs.initiate(config)
rs.status()查看副本集状态
可以看到一个主节点,三个子节点
2)一次性插入多条文档记录
首先,我们需要创建一个集合并插入多条文档。假设我们有一个名为 users 的集合:
use test
// 创建集合
db.createCollection("users");
// 插入多条文档,要求大多数节点(在这个案例中是2个节点)插入成功
db.users.insertMany([
{ _id: 1, name: "Alice", age: 29 },
{ _id: 2, name: "Bob", age: 34 },
{ _id: 3, name: "Charlie", age: 42 }
], { writeConcern: { w: "majority" } });
这里的 writeConcern 设置为 majority,意味着操作必须在大多数节点上成功(即至少两个节点)才能被认为是成功的。
在27017端口插入多条数据
在27018端口查询
新开一个mongosh.exe
输入localhost:27018进入
db.users.find()
根据图得到结果可以被查询到
27019端口同理如下
也可以被查询到
由此可知,所有节点都成功插入信息
3)原子修改操作
现在我们要对其中一条文档进行修改,并设置为只要一个节点完成修改就可以返回成功信息:
// 假设我们要修改 Bob 的年龄
db.users.updateOne(
{ _id: 2 },
{ $set: { age: 35 } },
{ writeConcern: { w: 1 } }
);
这里的 writeConcern 设置为 1,表示只要一个节点确认这个修改操作,MongoDB 就会返回操作成功。
在27017端口进行修改
27018端口查询
27019端口查询
可以看到均可以成功看到被修改消息
实验二 索引性能比较
在同一台符合要求的单机上实现该实验。
(1)在5.3.1小节生成的大数据记录的基础上执行 find()explain()分析,记录分析结果
(2)在5.3.1小节生成的大数据记录的基础上加入字段索引,对该字段进行 find
Explain()分析,记录分析结果。
(3)删除 5.3.1 小节生成的大数据记录多余的数据,保留 200 条记录,再执行findexplain()分析,记录分析结果。
(4)删除所建立的索引,再执行 fndexplain()分析,记录分析结果。
(5)进行执行结果统计,制作出统计分析比较表,说明比较结论。
1) 在5.3.1小节生成的大数据记录的基础上执行 find()explain()分析,记录分析结果
在上次MONGODB一个案例中,生成了30万条数据,在这个基础上进行执行 find().explain() 分析
use test;
// 无索引情况
db.test.find({test: {$gt: 500}}).explain("executionStats");
我们现在用 $gt 操作符来查询 test 字段大于 500 的文档。
结果如下
可以看到关键信息
nReturned: 298,497 表示有这么多条文档符合查询条件并返回。
executionTimeMillis: 80 毫秒,是整个查询执行的时间。
totalKeysExamined: 0,因为没有使用索引,所以没有键被检查。
totalDocsExamined: 300,000 表明总共检查了30万条文档,这也是集合中的总
文档数。
2) 在5.3.1小节生成的大数据记录的基础上加入字段索引,对该字段进行 find
Explain()分析,记录分析结果。
加入字段索引并分析
首先,创建索引:
db.test.createIndex({test: 1});
然后再次执行查询分析:
db.test.find({test: {$gt: 500}}).explain("executionStats");
结果如下
works, advanced 均为 298497,表明工作过程和成功传递到下一阶段的文档数量相等,说明效率很高。
needTime, needYield 为 0,意味着没有因为资源或时间限制而需要额外的时间或yield操作。
executionTimeMillisEstimate: 489 毫秒,是对执行时间的估计,实际执行时间略高于这个估计值。
seeks: 1 表明只进行了一次索引查找,这表明索引扫描的效率很高。
3) 删除多余数据并分析
我们只保留前 200 条记录
use test;
// 删除 insertOrder 大于 200 的记录
db.test.remove({insertOrder: {$gt: 200}});
删除后,执行查询分析:
db.test.find({test: {$gt: 500}}).explain("executionStats");
4) 删除索引并分析
db.test.dropIndex({test: 1});
删除索引后,再次执行查询分析:
db.test.find({test: {$gt: 500}}).explain("executionStats");
统计分析比较表:
步骤 | 无索引(大量数据) | 有索引(大量数据) | 无索引(200条数据) | 有索引(200条数据) |
执行时间 (ms) | 80 | 501 | 7 | 10 |
扫描文档数量 | 300000 | 300000 | 603 | 603 |
返回文档数量 | 298497 | 298497 | 0 | 0 |
索引使用情况 | 无 | 使用 | 无 | 使用 |