MongoDB之索引

常用命令

查看表的索引

db.<table>.getIndexes()

查看表索引的大小

db.<table>.totalIndexSize()

重建索引

db.<table>.reIndex()

删除索引

db.COLLECTION_NAME.dropIndex("INDEX-NAME")
db.COLLECTION_NAME.dropIndexes()

_id 索引无法删除。

执行计划

参考:MongoDB干货系列2-MongoDB执行计划分析详解(1) | MongoDB中文社区、MongoDB - 执行计划 - 听雨危楼 - 博客园

-- 千万测试数据
for(var i=1;i<10000000;i++){ db.indexDemo.insert({_id:i , num:'index:'+i ,address:'address:i%9999'})}

默认的查询计划 queryPlanner

-- 不使用索引
db.indexDemo.find({num:'index:99999'}).explain()db.indexDemo.createIndex( { num: 1 } )
db.indexDemo.getIndexes()
db.indexDemo.dropIndex("num_1")
{"explainVersion" : "1","queryPlanner" : {"namespace" : "study.goods",                     【查询的表】"indexFilterSet" : false,                        【是否有indexfilter】"parsedQuery" : {                                【查询过滤条件】"qty" : {"$gt" : 50}},"queryHash" : "3DC2392F","planCacheKey" : "B7F8CFFA","maxIndexedOrSolutionsReached" : false,"maxIndexedAndSolutionsReached" : false,"maxScansToExplodeReached" : false,"winningPlan" : {                                【最优执行计划详细内容】"stage" : "FETCH",FETCH:通过返回的index扫描。COLLSCAN:全表扫描】"inputStage" : {                         【子stage】"stage" : "IXSCAN",              【表示进行索引扫描】"keyPattern" : {                 【扫描的索引内容】"qty" : 1},"indexName" : "qty_1",           【使用的索引名称】"isMultiKey" : false,            【是否多列索引。索引建立在array上时是true"multiKeyPaths" : {"qty" : [ ]},"isUnique" : false,"isSparse" : false,"isPartial" : false,"indexVersion" : 2,"direction" : "forward",         【查询的顺序:forward升序、backward降序】"indexBounds" : {                【索引扫描范围,没有制定范围就是[MaxKey,MinKey]"qty" : ["(50.0, inf.0]"]}}},"rejectedPlans" : [ ]                            【其它非最优的执行计划】},"command" : {"find" : "goods","filter" : {"qty" : {"$gt" : 50}},"sort" : {"qty" : 1},"$db" : "study"},"serverInfo" : {                                         【服务器信息】"host" : "fe9b0d04fcbd","port" : 27017,"version" : "5.0.5","gitVersion" : "d65fd89df3fc039b5c55933c0f71d647a54510ae"},"serverParameters" : {"internalQueryFacetBufferSizeBytes" : 104857600,"internalQueryFacetMaxOutputDocSizeBytes" : 104857600,"internalLookupStageIntermediateDocumentMaxSizeBytes" : 104857600,"internalDocumentSourceGroupMaxMemoryBytes" : 104857600,"internalQueryMaxBlockingSortMemoryUsageBytes" : 104857600,"internalQueryProhibitBlockingMergeOnMongoS" : 0,"internalQueryMaxAddToSetBytes" : 104857600,"internalDocumentSourceSetWindowFieldsMaxMemoryBytes" : 104857600},"ok" : 1
}

附加执行状态 executionStats

-- 在默认的执行计划信息上,多了 executionStats 信息
db.indexDemo.find({num:'index:99999'}).explain("executionStats")
{"explainVersion" : "1","queryPlanner" : {...},"executionStats" : {"executionSuccess" : true,                     【是否执行成功】"nReturned" : 1,                               【匹配到的文档数】"executionTimeMillis" : 0,                     【选择和查询执行计划所需时间。毫秒】"totalKeysExamined" : 1,											 【扫描的索引条目数】"totalDocsExamined" : 1,                       【扫描文档数】"executionStages" : {                          【最优执行计划的完整信息】"stage" : "FETCH",FETCH:根据索引结果去扫描文档】"nReturned" : 1,                             【stage=FETCH时,跟上面的nReturned一样】"executionTimeMillisEstimate" : 0,           【检索文档获得数据的时间】"works" : 2,                                 【执行查询阶段的各个工作以“单元”划分,这里表示工作单元数】"advanced" : 1,															 【返回到父阶段的结果数】"needTime" : 0,                              【中间结果返回给父级的工作循环次数】"needYield" : 0,"saveState" : 0,"restoreState" : 0,"isEOF" : 1,"docsExamined" : 1,"alreadyHasObj" : 0,"inputStage" : {...}}},"command" : {"find" : "indexDemo","filter" : {"num" : "index:99999"},"$db" : "study"},"serverInfo" : {...},"serverParameters" : {"internalQueryFacetBufferSizeBytes" : 104857600,"internalQueryFacetMaxOutputDocSizeBytes" : 104857600,"internalLookupStageIntermediateDocumentMaxSizeBytes" : 104857600,"internalDocumentSourceGroupMaxMemoryBytes" : 104857600,"internalQueryMaxBlockingSortMemoryUsageBytes" : 104857600,"internalQueryProhibitBlockingMergeOnMongoS" : 0,"internalQueryMaxAddToSetBytes" : 104857600,"internalDocumentSourceSetWindowFieldsMaxMemoryBytes" : 104857600},"ok" : 1
}

关键参数

耗时 executionTimeMillis

  • executionStats.executionTimeMillis:整体查询时间。
  • executionStats.executionStages.executionTimeMillisEstimate:检索Document获得数据的时间
  • executionStats.executionStages.inputStage.executionTimeMillisEstimate:扫描文档 Index所用时间

扫描数 nReturned

  • nReturned:查询结果返回的条目数
  • totalKeysExamined:总索引扫描的条目数
  • totalDocsExamined :总索引扫描的条目数

扫描数越少越好,理想情况:
nReturned = totalKeysExamined = otalDocsExamined

stage 参数表

类型描述
COLLSCAN全表扫描
IXSCAN索引扫描
FETCH根据索引去检索指定document
SHARD_MERGE将各分片的返回结果合并
SORT在内存中进行了排序
LIMIT限制返回数
SKIP使用skip进行跳过
IDHACK针对_id进行的查询
SHARDING_FILTER通过mongos对分片数据进行查询
COUNT利用db.coll.explain().count()之类进行count运算
TEXT全文索引
PROJECTION限定返回字段时候

返回最优与备选计划 allPlansExecution

db.indexDemo.find({num:'index:99999'}).explain("allPlansExecution")

慢查询分析

开启内置查询分析器

-- 开启内置查询分析器
db.setProfilingLevel([0,1,2],m)
0:不记录
1:记录超过阈值m的记录
2:记录所有读写操作-- 例子
db.setProfilingLevel(1,100)
db.setProfilingLevel(2)

查看监听结果

db.system.profile.find().sort({millis:-1}).limit(3)

结果分析

慢查询常见于:

  • 应用设计不合理;
  • 数据模型不合理;
  • 硬件配置;
  • 缺少索引;

explain 分析是否跑索引

创建索引

测试数据

db.goods.insertMany( [
{ item: "canvas", qty: 100, size: { h: 28, w: 35.5, uom: "cm" }, status:
"A" },
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status:
"A" },
{ item: "mat", qty: 85, size: { h: 27.9, w: 35.5, uom: "cm" }, status:
"A" },
{ item: "mousepad", qty: 25, size: { h: 19, w: 22.85, uom: "cm" },
status: "P" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status:
"P" },
{ item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status:
"D" },
{ item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status:
"D" },
{ item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" },
status: "A" },
{ item: "sketchbook", qty: 80, size: { h: 14, w: 21, uom: "cm" }, status:
"A" },
{ item: "sketch pad", qty: 95, size: { h: 22.85, w: 30.5, uom: "cm" },
status: "A" }
]);
db.inventory.insertMany([
{ _id: 1,item: "abc",stock: [{ size: "S", color: "red", quantity: 25 },{
size: "S", color: "blue", quantity: 10 },{ size: "M", color: "blue",
quantity: 50 }]},
{_id:2,item:"def",stock:[{size:"S",color:"blue",quantity:20},
{size:"M",color:"blue",quantity:5},{size:"M",color:"black",quantity:10},
{size:"L",color:"red",quantity:2}]},
{_id:3,item:"ijk",stock:[{size:"M",color:"blue",quantity:15},
{size:"L",color:"blue",quantity:100},{size:"L",color:"red",quantity:25}]}
])

单字段索引 Single Field

单列索引

db.<table>.createIndex(keys, options)
options:

  • 1:按照升序创建索引
  • -1:按照降序创建索引

db.indexDemo.find({num:"index:600"}).explain()db.indexDemo.createIndex({num:1})db.indexDemo.find({num:"index:600"}).explain()

给嵌入式字段创建索引

{"_id": ObjectId("570c04a4ad233577f97dc459"),"score": 1034,"location": { state: "NY", city: "New York" }
}-- 创建索引
db.<table>.createIndex( { "location.state": 1 } )-- 索引生效
db.<table>.find( { "location.state": "CA" } )
db.<table>.find( { "location.city": "Albany", "location.state": "NY" } )

给整个内嵌文档创建索引

{"_id": ObjectId("570c04a4ad233577f97dc459"),"score": 1034,"location": { state: "NY", city: "New York" }
}-- 创建索引
db.<table>.createIndex( { location: 1 } )-- 索引生效
db.records.find( { location: { city: "New York", state: "NY" } } )

复合索引 Compound Index

db.collection.createIndex( { <field1>: <type>, <field2>: <type2>, ... } )

⚠️不能创建具有hashed索引类型的复合索引。如果试图创建包含hashed索引字段的复合索引,将收到一个错误。

{"_id": ObjectId(...),"item": "Banana","category": ["food", "produce", "grocery"],"location": "4th Street Store","stock": 4,"type": "cases"
}-- 创建索引
db.<table>.createIndex( { "item": 1, "stock": 1 } )-- 索引生效
db.<table>.find( { item: "Banana" } )
db.<table>.find( { item: "Banana", stock: { $gt: 5 } } )

⚠️特别注意字段的顺序与排序。复合索引遵循最左匹配原则。

多键索引 Multikey indexes

支持对数组中每个元素创建索引。元素类型:string、number、 nested documents(嵌套文档) 。

number 类型数组

db.inventory.remove({})
db.inventory.insertMany([{ _id: 5, type: "food", item: "aaa", ratings: [ 5, 8, 9 ] },{ _id: 6, type: "food", item: "bbb", ratings: [ 5, 9 ] },{ _id: 7, type: "food", item: "ccc", ratings: [ 9, 5, 8 ] },{ _id: 8, type: "food", item: "ddd", ratings: [ 9, 5 ] },{ _id: 9, type: "food", item: "eee", ratings: [ 5, 9, 5 ] }
])
-- 没加索引
db.inventory.find({ratings:[5,9]}).explain("executionStats")
-- 给数组加索引
db.inventory.createIndex( { ratings: 1 } )

嵌套文档 类型数组

单列索引
db.inventory.dropIndexes()db.inventory.insertMany([{ type: "food", item: "aaa", ratings: [ 5, 8, 9 ], size:[{w:10,h:165},{w:9,h:158}] },{type: "food", item: "aaa", ratings: [ 5, 8, 9 ], size:[{w:11,h:175},{w:7,h:142}] },{type: "food", item: "aaa", ratings: [ 5, 8, 9 ], size:[{w:15,h:163},{w:8,h:157}] }
])
-- 无索引查询
db.inventory.find({"size.w":10}).explain("executionStats")
-- 添加索引
db.inventory.createIndex({"size.w":1})
复合索引
-- 添加复合索引
db.inventory.createIndex( {"size.w":1,"size.h":2})
-- 查询
db.inventory.find({"size.w":10}).explain("executionStats")
db.inventory.find({"size.w":10},{"size.h":10}).explain("executionStats")

地理空间索引 Geospatial Index

  • 2dsphere索引,用于存储和查找球面上的点
  • 2d索引,用于存储和查找平面上的点
db.company.insert({loc : { type: "Point", coordinates: [ 116.482451, 39.914176 ] },name:"来广营地铁站-叶青北园",category : "Parks"}
)
# 2dsphere 或者 2d 。可以建立组合索引。
db.company.ensureIndex( { loc : "2dsphere" } )db.company.find({"loc" : {"$geoWithin" : {"$center":[[116.482451,39.914176],0.05]}}
})

全文索引 Text Index

一个集合最多一个全文索引,可以覆盖多个字段。中文分词支持不佳(推荐ES)。

db.<table>.createIndex({"fieldA": "text"})db.<table>.createIndex({fieldA: "text",fieldB: "text"})db.store.insert([
{ _id: 1, name: "Java Hut", description: "Coffee and cakes" },
{ _id: 2, name: "Burger Buns", description: "Gourmet hamburgers" },
{ _id: 3, name: "Coffee Shop", description: "Just coffee" },
{ _id: 4, name: "Clothes Clothes Clothes", description: "Discountclothing" },
{ _id: 5, name: "Java Shopping", description: "Indonesian goods" }
])db.store.createIndex( { name: "text", description: "text" } )db.store.find( { $text: { $search: "java coffee shop" } } )
{ "_id" : 3, "name" : "Coffee Shop", "description" : "Just coffee" }
{ "_id" : 1, "name" : "Java Hut", "description" : "Coffee and cakes" }
{ "_id" : 5, "name" : "Java Shopping", "description" : "Indonesian goods" }

哈希索引 Hashed Index

只用于等值查询。

db.<table>.createIndex({"字段": "hashed"})

MongoDB 索引底层数据结构

文档类型数据库使用 BSON 格式保存数据,比 RDBMS 存储更方便。RDBMS 适合用于多表之间的关联的场景,而 BSON 可以把关联的数据存在一起。
比如MySQL使用 RDBMS 格式,数据的关联性强,范围查询普遍。所以底层使用B+树。
MongoDB使用B树,通过索引能更快访问,但不适合范围查询。
image.png
B树特点

  • 多路搜索。
  • 节点存储既存储索引又存储数据。
  • 关键字在树中只出现一次。

跟B+树的区别:

  • 叶子节点之间的指向。
  • 数据保存的位置。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/418011.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++——函数的调用

1&#xff0c;函数功能的调用 功能&#xff1a;使用定义好的函数 语法&#xff1a;函数名&#xff08;参数&#xff09; 示例&#xff1a; #include<bits/stdc.h> using namespace std; //定义加法函数 int add(int num1,int num2){int sumnum1num2;return sum; …

ECTouch 电商微信小程序 SQL注入漏洞复现(CVE-2023-39560)

0x01 产品简介 ECTouch是一款开源的电商系统,为中小企业提供最佳的新零售解决方案 0x02 漏洞概述 ECTouch 电商系统 /ectouch-main/include/apps/default/helpers/insert.php 文件中第285行的 insert_bought_notes 函数中,传入的 $arr[id] 参数未进行验证和过滤,导致未经…

JavaWeb-Cookie与Session

一、概念 是否还记得我们在HTTP概念中提到&#xff1a;HTTP的一大特点是无状态&#xff0c;这意味着多次HTTP请求之间是无法共享数据的。而在请求之间共享一些数据又是我们期望达到的效果。&#xff08;例如登录的记住我功能&#xff09;于是便有了会话跟踪技术&#xff0c;而…

mysql 下载和安装和修改MYSQL8.0 数据库存储文件的路径

一、第一步:下载步骤 下载链接&#xff1a;MySQL :: Download MySQL Installer 选择版本8.0.35&#xff0c;社区版&#xff0c; 点击 Download 下载 安装包 二、第二步:安装步骤 添加环境变量&#xff0c;C:\Program Files\MySQL\MySQL Server 8.0\bin 可以点开MySQL 8.0 Co…

基于python socket实现TCP/UDP通信

两个应用程序如果需要进行通讯最基本的一个前提就是能够唯一的标示一个进程&#xff0c;我们知道IP层的ip地址可以唯一标示主机&#xff0c;而TCP层协议和端口号可以唯一标示主机的一个进程&#xff0c;这样我们可以利用ip地址&#xff0b;协议&#xff0b;端口号唯一标示网络中…

【蓝桥杯EDA设计与开发】立创开源社区分享的关于蓝桥被EDA真题与仿真题的项目分析

立创开源社区内有几个项目分享了往年 EDA 设计题目与仿真题&#xff0c;对此展开了学习。 【本人非科班出身&#xff0c;以下对项目的学习仅在我的眼界范围内发表意见&#xff0c;如有错误&#xff0c;请指正。】 项目一 来源&#xff1a;第十四届蓝桥杯EDA赛模拟题一 - 嘉立…

掌握使用CXF快速开发webservice服务和生成client端技能

文章目录 前言1.安装和配置cxf环境2.创建一个通过maven管理的java项目并引入相关cxf依赖3.使用cxf提供的类编写webservice服务端并发布服务3.1 定义一个webservice服务接口HelloWorld3.2 编写HelloWorld实现类3.3 通过JaxWsServerFactoryBean发布webservice服务3.4 在浏览器中通…

实用干货:最全的Loading动画合集网站!复制即用

大家好&#xff0c;我是大澈&#xff01; 本文约1000字&#xff0c;整篇阅读大约需要2分钟。 感谢关注微信公众号&#xff1a;“程序员大澈”&#xff0c;免费领取"面试礼包"一份&#xff0c;然后免费加入问答群&#xff0c;从此让解决问题的你不再孤单&#xff01…

写点啥 内核调优吧

一、命令xargs --------------- 参数替换 由于很多命令不支持管道|来传递参数&#xff0c;xargs用于产生某个命令的参数&#xff0c;xargs 可以读入 stdin 的数 据&#xff0c;并且以空格符或回车符将 stdin 的数据分隔成为参数&#xff0c;另外许多命令不能接受过多参数&am…

【Linux】相关背景及环境搭建

前言&#xff1a; 认识 Linux, 了解 Linux 的相关背景&#xff0c;学会如何使用云服务器&#xff0c;掌握使用远程终端工具 xshell 登陆 Linux 服务器 文章目录 一、Linux介绍1.1 关于UNIX1.2 Linux的诞生及发展历程1.3 Linux开源1.4 Linux在各个行业的现状1.5 发行版本 二、Li…

【设计模式】腾讯二面:自动贩卖机/音频播放器使用了什么设计模式?

状态模式是什么&#xff1f; 状态模式&#xff0c;也被称作状态对象模式&#xff0c;是一种行为设计模式。 当一个对象的内在状态改变时&#xff0c;允许改变其行为&#xff0c;这个对象看起来像是改变了其类。 它让对象在其内部状态改变时改变自己的行为。外部调用者无需了…

Docker(八)高级网络配置

作者主页&#xff1a; 正函数的个人主页 文章收录专栏&#xff1a; Docker 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01; 高级网络配置 注意&#xff1a;本章属于 Docker 高级配置&#xff0c;如果您是初学者&#xff0c;您可以暂时跳过本章节&#xff0c;直接学习…