【Mongodb】视图 && 索引
准备工作
准备2个集合的数据,后面视图和索引都会用到
1个订单集合,一个收款信息集合
- var orders = new Array();
- var shipping = new Array();
- var addresses = ["广西省玉林市", "湖南省岳阳市", "湖北省荆州市", "甘肃省兰州市", "吉林省松原市", "江西省景德镇", "辽宁省沈阳市", "福建省厦门市", "广东省广州市", "北京市朝阳区"];
- for (var i = 10000; i < 20000; i++) {
- var orderNo = i + Math.random().toString().substr(2, 5);
- orders[i] = { orderNo: orderNo, userId: i, price: Math.round(Math.random() * 10000) / 100, qty: Math.floor(Math.random() * 10) + 1, orderTime: new Date(new Date().setSeconds(Math.floor(Math.random() * 10000))) };
- var address = addresses[Math.floor(Math.random() * 10)];
- shipping[i] = { orderNo: orderNo, address: address, recipienter: "Wilson", province: address.substr(0, 3), city: address.substr(3, 3) }
- }
- db.order.insert(orders);
- db.shipping.insert(shipping);
视图
概述
A MongoDB view is a queryable object whose contents are defined by an aggregation pipeline on other collections or views. MongoDB does not persist the view contents to disk. A view’s content is computed on-demand when a client queries the view. MongoDB can require clients to have permission to query the view. MongoDB does not support write operations against views.
Mongodb的视图基本上和SQL的视图一样
- 数据源(集合或视图)
- 提供查询
- 不实际存储硬盘
- 客户端发起请求查询时计算而得
1. 创建视图
有两种方法创建视图
- db.createCollection(
- "<viewName>",
- {
- "viewOn" : "<source>",
- "pipeline" : [<pipeline>],
- "collation" : { <collation> }
- }
- )
- db.createView(
- "<viewName>",
- "<source>",
- [<pipeline>],
- {
- "collation" : { <collation> }
- }
- )
一般使用db.createView
viewName : 必须,视图名称
source : 必须,数据源,集合/视图
[<pipeline>] : 可选,一组管道,可见管道是Mongodb比较重要的一环
1.1 单个集合创建视图
假设现在查看当天最高的10笔订单视图,例如后台某个地方需要实时显示金额最高的订单
- db.createView(
- "orderInfo", //视图名称
- "order", //数据源
- [
- //筛选符合条件的订单,大于当天,这里要注意时区
- { $match: { "orderTime": { $gte: ISODate("2020-04-13T16:00:00.000Z") } } },
- //按金额倒序
- { $sort: { "price": - } },
- //限制10个文档
- { $limit: },
- //选择要显示的字段
- //0: 排除字段,若字段上使用(_id除外),就不能有其他包含字段
- //1: 包含字段
- { $project: { _id: , orderNo: , price: , orderTime: } }
- ]
- )
然后就可以直接使用orderInfo这个视图查询数据
- db.orderInfo.find({})
返回结果
- { "orderNo" : "", "price" : , "orderTime" : ISODate("2020-04-14T13:49:42.220Z") }
- { "orderNo" : "", "price" : 99.99, "orderTime" : ISODate("2020-04-14T15:08:07.240Z") }
- { "orderNo" : "", "price" : 99.99, "orderTime" : ISODate("2020-04-14T15:15:41.158Z") }
- { "orderNo" : "", "price" : 99.98, "orderTime" : ISODate("2020-04-14T13:41:07.199Z") }
- { "orderNo" : "", "price" : 99.98, "orderTime" : ISODate("2020-04-14T13:31:58.150Z") }
- { "orderNo" : "", "price" : 99.98, "orderTime" : ISODate("2020-04-14T15:15:35.162Z") }
- { "orderNo" : "", "price" : 99.94, "orderTime" : ISODate("2020-04-14T14:13:02.160Z") }
- { "orderNo" : "", "price" : 99.93, "orderTime" : ISODate("2020-04-14T15:17:25.210Z") }
- { "orderNo" : "", "price" : 99.92, "orderTime" : ISODate("2020-04-14T13:09:41.196Z") }
- { "orderNo" : "", "price" : 99.92, "orderTime" : ISODate("2020-04-14T15:16:15.187Z") }
1.2 多个集合创建视图
其实跟单个是集合是一样,只是多了$lookup连接操作符,视图根据管道最终结果显示,所以可以关联多个集合(若出现这种情况就要考虑集合设计是否合理,mongodb本来就是文档型数据库)
- db.orderDetail.drop()
- db.createView(
- "orderDetail",
- "order",
- [
- { $lookup: { from: "shipping", localField: "orderNo", foreignField: "orderNo", as: "shipping" } },
- { $project: { "orderNo": , "price": , "shipping.address": } }
- ]
- )
查询视图,得到如下结果
- { "_id" : ObjectId("5e95af8c4ef6faf974b4a6c3"), "orderNo" : "", "price" : 85.94, "shipping" : [ { "address" : "北京市朝阳区" } ] }
- { "_id" : ObjectId("5e95af8c4ef6faf974b4a6c4"), "orderNo" : "", "price" : 29.04, "shipping" : [ { "address" : "吉林省松原市" } ] }
- { "_id" : ObjectId("5e95af8c4ef6faf974b4a6c5"), "orderNo" : "", "price" : 90.69, "shipping" : [ { "address" : "湖南省岳阳市" } ] }
- { "_id" : ObjectId("5e95af8c4ef6faf974b4a6c6"), "orderNo" : "", "price" : 75.05, "shipping" : [ { "address" : "辽宁省沈阳市" } ] }
- { "_id" : ObjectId("5e95af8c4ef6faf974b4a6c7"), "orderNo" : "", "price" : 76.84, "shipping" : [ { "address" : "江西省景德镇" } ] }
- { "_id" : ObjectId("5e95af8c4ef6faf974b4a6c8"), "orderNo" : "", "price" : 60.25, "shipping" : [ { "address" : "江西省景德镇" } ] }
- { "_id" : ObjectId("5e95af8c4ef6faf974b4a6c9"), "orderNo" : "", "price" : 19.14, "shipping" : [ { "address" : "广东省广州市" } ] }
- { "_id" : ObjectId("5e95af8c4ef6faf974b4a6ca"), "orderNo" : "", "price" : 31.5, "shipping" : [ { "address" : "北京市朝阳区" } ] }
- { "_id" : ObjectId("5e95af8c4ef6faf974b4a6cb"), "orderNo" : "", "price" : 76.16, "shipping" : [ { "address" : "吉林省松原市" } ] }
- { "_id" : ObjectId("5e95af8c4ef6faf974b4a6cc"), "orderNo" : "", "price" : 93.98, "shipping" : [ { "address" : "辽宁省沈阳市" } ] }
可以看到,mongodb不是像SQL那样把连接的表当成列列出,而是把连接结果放在数组里面,这很符合Mongodb文档型结构。
2. 修改视图
假设现在需要增加一个数量的字段
- db.runCommand({
- collMod: "orderInfo",
- viewOn: "order",
- pipeline: [
- { $match: { "orderTime": { $gte: ISODate("2020-04-13T16:00:00.000Z") } } },
- { $sort: { "price": - } },
- { $limit: },
- //增加qty
- { $project: { _id: , orderNo: , price: , qty: , orderTime: } }
- ]
- })
当然,也可以删除视图,重新用db.createView()创建视图
3. 删除视图
- db.orderInfo.drop();
索引
概述
Indexes support the efficient execution of queries in MongoDB. Without indexes, MongoDB must perform a collection scan, i.e. scan every document in a collection, to select those documents that match the query statement. If an appropriate index exists for a query, MongoDB can use the index to limit the number of documents it must inspect.
索引能提供高效的查询,没有索引的查询,mongole执行集合扫描,相当于SQL SERVER的全表扫描,扫描每一个文档。
数据存在存储介质上,大多数情况是为了查询,查询的快慢直接影响用户体验,mongodb索引也是空间换时间,添加索引,CUD操作都会导致索引重新生成,影响速度。
1. 准备工作
1.1 准备200W条数据
- var orderNo = * ;
- for (var i = ; i < ; i++) {
- //分批次插入,每次20000条
- var orders = new Array();
- for (var j = ; j < ; j++) {
- var orderNo = orderNo++;
- orders[j] = { orderNo: orderNo, userId: i + j, price: Math.round(Math.random() * ) / , qty: Math.floor(Math.random() * ) + , orderTime: new Date(new Date().setSeconds(Math.floor(Math.random() * ))) };
- }
- //不需写入确认
- db.order.insert(orders, { writeConcern: { w: } });
- }
1.2 mongodb的查询计划
- db.collection.explain().<method(...)>
一般使用执行统计模式,例如
- db.order.explain("executionStats").find({orderNo:})
返回的executionStats对象字段说明
部分字段说明
字段 | 说明 |
---|---|
executionSuccess | 是否执行成功 |
nReturned | 返回匹配文档数量 |
executionTimeMillis | 执行时间,单位:毫秒 |
totalKeysExamined | 索引检索数目 |
totalDocsExamined | 文档检索数目 |
查看未加索引前查询计划
- db.order.explain("executionStats").find({orderNo:})
截取部分返回结果,可以看出
- executionTimeMillis : 用时1437毫秒
- totalDocsExamined : 扫描文档200W
- executionStages.stage : 集合扫描
- "executionStats" : {
- "executionSuccess" : true,
- "nReturned" : ,
- "executionTimeMillis" : ,
- "totalKeysExamined" : ,
- "totalDocsExamined" : ,
- "executionStages" : {
- "stage" : "COLLSCAN",
1.3 查看当前集合统计信息
- db.order.stats()
截取部分信息,可以看出现在存储文件大小大概为72M
- {
- "ns" : "mongo.order",
- "size" : ,
- "count" : ,
- "avgObjSize" : ,
- "storageSize" : ,
2. 创建索引
- db.order.createIndex({ orderNo: }, { name: "ix_orderNo" })
索引名称不是必须,若不指定,按 字段名称_排序类型组合自动生成,索引名称一旦创建不能修改,若要修改,只能删除索引重新生成索引,建议还是建索引的时候就把索引名称设置好。
2.1 执行查询计划
- db.order.explain("executionStats").find({orderNo:})
截取部分结果,直观就可以感觉查询速度有了质的提升,再看查询计划更加惊讶
- nReturned : 匹配到1个文档
- executionTimeMillis : 0,呃。。
- totalKeysExamined : 总共检索了1个索引
- totalDocsExamined : 总共检索了1个文档
- executionStages.stage : FETCH,根据索引去检索指定文档,像SQL的Index Seek
- "executionStats" : {
- "executionSuccess" : true,
- "nReturned" : ,
- "executionTimeMillis" : ,
- "totalKeysExamined" : ,
- "totalDocsExamined" : ,
- "executionStages" : {
- "stage" : "FETCH"
这里只介绍最简单的单个字段索引,mongodb还有很多索引
- 复合索引(Compound Indexes):对多个字段做索引
- 多键索引(Multikey Indexes): 一个字段多个值做索引,通常是数组
- 全文索引(Text Indexes): 对文本检索,可以对字段设置不同权重
- 通配符索引(Wildcard Indexes):可以将对象的所有/指定的值做索引
- 更多
转发请标明出处:https://www.cnblogs.com/WilsonPan/p/12704474.html
【Mongodb】视图 && 索引的更多相关文章
- 84. 从视图索引说Notes数据库(下)
作用和代价上文介绍了关系型数据库里的索引.Notes数据库里的索引隐藏在视图概念里(本文的讨论仅仅针对Notes的视图索引,不包括全文索引.).开发者创建的视图仅仅是存放在数据库里的一条设计文档.数据 ...
- MongoDB的索引(三)
MongoDB的索引: 1. _id索引 该索引是大多数集合默认创建的索引,也就是说用户每插入一个数据,MongoDB会自动生成一条唯一的_id字段. 2. 单键索引 单键索引是最普通的索引,它不会自 ...
- MongoDB 覆盖索引查询
MongoDB 覆盖索引查询 官方的MongoDB的文档中说明,覆盖查询是以下的查询: 所有的查询字段是索引的一部分 所有的查询返回字段在同一个索引中 由于所有出现在查询中的字段是索引的一部分, Mo ...
- 83. 从视图索引说Notes数据库(上)
索引是数据库系统重要的feature,不管是传统的关系型数据库还是时兴的NoSQL数据库,它攸关查询性能,因而在设计数据库时须要细加考量.然而,Lotus Notes隐藏技术底层.以用户界面为导向.追 ...
- MongoDB数据库索引
前面的话 索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录.这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查 ...
- MongoDB数据库索引构建情况分析
前面的话 本文将详细介绍MongoDB数据库索引构建情况分析 概述 创建索引可以加快索引相关的查询,但是会增加磁盘空间的消耗,降低写入性能.这时,就需要评判当前索引的构建情况是否合理.有4种方法可以使 ...
- MongoDB索引(一) --- 入门篇:学习使用MongoDB数据库索引
这个系列文章会分为两篇来写: 第一篇:入门篇,学习使用MongoDB数据库索引 第二篇:进阶篇,研究数据库索引原理--B/B+树的基本原理 1. 准备工作 在学习使用MongoDB数据库索引之前,有一 ...
- 第五章 MySQL事务,视图,索引,备份和恢复
第五章 MySQL事务,视图,索引,备份和恢复 一.事务 1.什么是事务 事务是一种机制,一个操作序列,它包含了一组数据库操作命令,并且把所有的命令作为一个整体一起向系统提交或撤销操作请求.要么都执行 ...
- MongoDb进阶实践之七 MongoDB的索引入门
一.引言 好久没有写东西了,MongoDB系列的文章也丢下好长时间了.今天终于有时间了,就写了一篇有关索引的文章.一说到"索引",用过关系型数据库的人都应该知道它是一个什么 ...
- 给MongoDB添加索引
用过数据库的都知道,数据库索引与书籍的索引类似,都是用来帮助快速查找的. MongoDB的索引跟关系型数据库的索引几乎一致. 1. 索引的创建 mongodb采用ensureInd ...
随机推荐
- 干货来啦。Flask框架看这一篇就够了,关注不迷路,Jeff带你看源码。开发技术时时更新
目录 一.初识Flask 1.1 什么是flask? 1.2 为什么要有flask? 二.Flask快速启动 三.Flask四剑客 三.flask的配置文件 可以配置的属性 四.flask路由 4.1 ...
- libfastcommon总结(〇)
libfastcommon提供众多基础功能,该系列笔记将进行学习介绍. load_local_host_ip_addrs 进行加载主机上所有网卡的IPv4的地址. iniLoadFromFile 从文 ...
- Java 基础(六):循环
循环 老生常谈的一个控制流程了,我们在是使用数组和集合的时候,遍历元素的时候经常会用到循环的结构,Java具有非常灵活的三种循环机制: 根据是否知道循环的次数可以为分为while循环,do...whi ...
- win10安装ubuntu子系统和图形界面
子系统可以很方便的调用windows的文件(在/mnt里就有各个盘),也可以在windows里用VScode编辑linux的文件.还是很方便的.也可以切出去用QQ微信. 安装子系统参考教程:https ...
- ERP系统功能及部署方式
ERP是对企业经营过程中的一些事项进行系统化管理的一种软件,所以ERP软件包含企业经营过程中需要用到的多种功能管理模块,并且ERP软件有两种部署方式.下面一起来了解一下相关的知识吧! ERP系统的功能 ...
- 10个python爬虫入门实例
昨天和伙伴萌一块学习,写了几个简单的入门实例 涉及主要知识点: web是如何交互的 requests库的get.post函数的应用 response对象的相关函数,属性 python文件的打开,保存 ...
- canvas绘制折线图
效果图: 重难点: 1.画布左上角的顶点的坐标为(0 ,0),右下角的坐标最大,与平常思维相反 2.数据的处理 html代码: <!DOCTYPE html><html lang=& ...
- MySQL----DML(增删改表中数据)
##DML:增删改表中的数据 1.添加数据 *语法: * insert into 表名(列名1,列名2,...列名n) values (值1,值2,...值n); *注意: 1.列名和值要一一对应. ...
- LeetCode#1047-Remove All Adjacent Duplicates In String-删除字符串中的所有相邻重复项
一.题目 给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们. 在 S 上反复执行重复项删除操作,直到无法继续删除. 在完成所有重复项删除操作后返回最终的字符串.答案 ...
- 详细解析kafka之 kafka消费者组与重平衡机制
消费组组(Consumer group)可以说是kafka很有亮点的一个设计.传统的消息引擎处理模型主要有两种,队列模型,和发布-订阅模型. 队列模型:早期消息处理引擎就是按照队列模型设计的,所谓队列 ...