中国建设银行注册网站,新乡网站建设哪家便宜,wordpress播放插件,河北省建设部网站概述
分类
索引的分类#xff1a;
按照索引包含的字段数量#xff0c;可分为单键索引#xff08;单字段索引#xff09;和组合索引#xff08;联合索引、复合索引#xff09;按照索引字段的类型#xff0c;可以分为主键索引和非主键索引按照索引节点与物理记录的对应…概述
分类
索引的分类
按照索引包含的字段数量可分为单键索引单字段索引和组合索引联合索引、复合索引按照索引字段的类型可以分为主键索引和非主键索引按照索引节点与物理记录的对应方式来分可以分为聚簇索引和非聚簇索引其中聚簇索引是指索引节点上直接包含了数据记录而后者则仅仅包含一个指向数据记录的指针按照索引的特性不同可分为唯一索引、稀疏索引、文本索引、地理空间索引等
索引介绍
单键索引和复合索引
创建单键索引db.user.ensureIndex({ income: 1});。
单字段索引对内嵌字段创建索引db.user.ensureIndex({ health.height: 1}); // 健康指标信息。
创建复合索引db.user.ensureIndex({ income: 1, health.height: 1});。
数组索引
数组索引也被称为多值索引multikey index当对数组型的字段创建索引时这个索引就是多值的。多值索引在使用上与普通索引并没有什么不同只是在索引键上会同时产生多个值。数组索引必然会使索引的条目和体积发生膨胀。
多值索引和复合索引可以一起使用即复合索引前面的字段是非数组类型后面的字段是数组类型这个先后顺序和关系型数据库组合索引最左匹配原则是一个意思。MongoDB不支持一个复合索引中同时出现多个多值索引即不允许出现多个数组类型字段。
db.user.ensureIndex({ age: 1, hobbies: 1}); // OK, 可以有多个爱好
db.user.ensureIndex({ hobbies: 1, careers: 1}); // wrong, 职业经历(生涯)地理空间索引
LBSLocation Based Service基于地理位置的检索。
2dsphere
MongoDB有两种类型的地理空间索引2dsphere和2d。2dsphere索引可以与基于WGS84基准的地球球面几何模型一起使用。这个基准将地球表面模拟成一个扁圆球体这意味着在两极会比较扁。使用 2dsphere 索引的距离计算考虑到地球的形状提供比2d索引更准确的距离处理如计算两个城市之间的距离。在存储二维平面上的点时使用2d索引。
2dsphere允许以GeoJSON格式指定点、线和多边形。点由一个二元数组给出[经度,纬度]即[longitude,latitude]。GeoJSON格式是固定的
location : {type : Point,coordinates : [50, 2]
}即type和coordinates两个字段名不能更改type枚举值有Point、LineString、Polygon。location可以使用其他名称如loc。
创建一个地理空间索引db.shop.createIndex({ loc: 2dsphere})。可使用三种类型的地理空间查询交集intersection、包含within和接近nearness。
查询
db.shop.find({loc: {$near: {$geometry: {type: Point, coordinates: [121.615, 31.190] } },$maxDistance: 1000,}
})$near操作符用于实现附近店铺的检索返回数据结果会按距离排序。$geometry操作符用于指定一个GeoJSON格式的地理空间对象typePoint表示地理坐标点coordinates则是用户当前所在的经纬度位置$maxDistance限定最大距离单位是米。
注意点
MongoDB的地理空间检索基于WGS84坐标系在与一些地图平台集成时需要注意转换如GCJ-02火星坐标系、BD-09百度中国坐标系MongoDB 4.0版本之后near可以用于分片集合sharded collection而在此版本之前可以使用geoNear聚合操作来代替
2d
对于非球面地图电子游戏地图、时间序列数据等可使用2d索引代替2dsphere索引db.game.createIndex({ tile: 2d }, );
默认情况下2d 索引会假设取值范围为-180到180。如果希望对边界大小进行调整则可以指定最小值和最大值作为createIndex的选项db.game.ensureIndex({ tile: 2d}, {min: -1000, max: 1000});
2d索引支持$geoWithin、$nearSphere和$near查询选择器。
应该使用 $geoWithin查询在平面上定义的形状内的点。$geoWithin可以查询矩形、多边形、圆形或球体内的所有点它使用$geometry运算符来指定 GeoJSON 对象。
db.game.find({tile: {$geoWithin: {$box: [[0, 0], [10, 10]]}}}); // 查询左下角为[0, 0]、右上角为[10, 10]的矩形内的文档即坐标
db.game.find({tile: {$geoWithin: {$center: [[0, 0], 5]}}}); // 查询圆心为[0, 0]、半径为5的圆形内的坐标
db.game.find({tile: {$geoWithin: {$polygon: [[0, 0], [3, 6], [3, 0]]}}}); // 查询三个点指定的三角形(多边形)内的所有文档由于历史遗留原因MongoDB支持在平面2d索引上执行球面查询结合$geoWithin和$centerSphere运算符。指定一个数组其中包括圆心坐标和以弧度为单位的圆半径db.game.find({tile: {$geoWithin: {$centerSphere: [[0, 0], 0.01]}}});。
临近查询会返回距离给定点最近的坐标对的文档并按照距离对结果进行排序db.game.find({tile: {$near: [0, 0]}});
全文搜索索引
MongoDB Atlas全文搜索索引full-text search index基于Apache Lucene。
MongoDB text索引支持全文搜索不同于精确匹配搜索、模糊搜索、正则表达式搜索。text索引需要一定数量的与被索引字段中单词成比例的键。创建text索引可能会消耗大量的系统资源。有分片时则还会减慢数据移动的速度当迁移到一个新分片时所有文本都必须重新进行索引。
创建全文索引
db.articles.createIndex(
{title: text, body: text},
{weights : {title : 3, body : 2}}
)全文索引中的字段顺序并不重要等同对待。如果要区别对待可通过weights对每个字段指定权重来控制不同字段的相对重要性。索引一旦创建就不能改变字段的权重除非删除索引再重建。
对于某些集合如果不知道文档包含哪个字段。可以使用$**在文档的所有字符串字段上创建全文本索引。这样做不仅会对顶层的字符串字段建立索引也会搜索内嵌文档和数组中的字符串字段。
文本索引存在诸多限制如并未提供中文分词功能应用场景有限。
TTL索引
并非所有的数据都需要持久化存储即过了一定时间段后可以执行硬删除如监控业务日志。TTL索引对于此场景提供支持。
TTL索引需要声明在一个日期类型的字段上db.sysLog.ensureIndex({ createDate: 1}, { expireAfterSeconds: 3600 });。为systemlog集合声明一个TTL索引指向createdDate字段expireAfterSeconds3600表示数据将在createdDate之后3600秒1小时后过期。
MongoDB会在周期性运行的后台线程中对该集合进行检查及数据清理工作。TTL索引具有普通索引的功能同样可以用于加速数据的查询。
修改TTL索引过期时间db.runCommand({collMod: sysLog, index: {keyPattern: {createDate: 1}, expireAfterSeconds: 7200 }});
需要注意以下限制
只能支持单个字段且必须是非_id字段TTL索引不能用于固定集合TTL索引无法保证及时的数据老化MongoDB会通过后台的TTL Monitor定时器来清理老化数据典型的间隔时间是1分钟。当然如果在数据库负载过高的情况下TTL的行为则会进一步受到影响TTL索引对于数据的清理仅仅使用remove命令并不是很高效。TTL Monitor在运行期间对系统CPU、磁盘都会造成一定的压力。相比之下按日期分表的方式操作会更加高效
条件索引
partial index条件索引允许只对部分文档建立索引。
db.book.createIndex({ name: 1}, { partialFilterExpression: {rateing: {$gt: 8 } } });上面的SQL对书籍评分超过8分的文档才创建索引。
稀疏索引
模糊索引
索引特性
唯一性索引
通过uniquetrue选项可将索引定义为唯一性索引db.user.ensureIndex({ name: 1 }, { unique: true });。
也可用于复合索引db.book.ensureIndex({ type: 1, title: 1}, { unique: true }); // 分类下的书籍标题保持唯一性。
也可用于嵌套文档db.user.ensureIndex({ health.height: 1}, { unique: true });。
嵌套文档的唯一性约束根据不同的MongoDB版本其行为不太一致。以6.0.5版本来说字段的位置无所谓MongoDB会识别出来 对数组索引使用唯一性约束可以保证所有的文档之间不会存在重叠的数组元素db.user.ensureIndex({ careers: 1}, { unique: true });。数组索引上的唯一性约束并无法保证同一个文档中包含重复的元素。需要从应用层进行distinct去重处理如使用Set集合。
db.user.insertOne({careers: [DevOps, IT manager]});
db.user.insertOne({careers: [doctor, nurse, doctor]});注意事项
唯一性索引对于文档中缺失的字段会使用null值代替因此不允许存在多个文档缺失索引字段的情况。
集合现在有2条数据 对一个新增字段创建索引db.user.ensureIndex({ health.height: 1}, { unique: true });报错Write failed with error code 11000 and error message Index build failed: caused by :: E11000 duplicate key error collection: test.user index: health.height_1 dup key: { health.height: null }
对于分片的集合唯一性约束必须匹配分片规则。换句话说为了保证全局的唯一性分片键必须作为唯一性索引的前缀字段。
ensureIndex和createIndex
进阶
explain
和关系型数据库一样MongoDB也提供explain命令帮助评估指定查询模型query model的计划。
命令db.getSiblingDB(corpus).getCollection(mds_factors).find().explain(executionStats);执行输出
[{$clusterTime: {clusterTime: {$timestamp: {t: 1706014465, i: 1}},signature: {hash: {$binary: {base64: ZFjBv3to5hMaqrdVckd9c0qZh7M, subType: 00}},keyId: 7281537397286764545}},executionStats: {executionSuccess: true,nReturned: 1,executionTimeMillis: 5,totalKeysExamined: 1,totalDocsExamined: 1,executionStages: {stage: FETCH,nReturned: 1,executionTimeMillisEstimate: 0,works: 2,advanced: 1,needTime: 0,needYield: 0,saveState: 0,restoreState: 0,isEOF: 1,invalidates: 0,docsExamined: 1,alreadyHasObj: 0,inputStage: {stage: IXSCAN,nReturned: 1,executionTimeMillisEstimate: 0,works: 2,advanced: 1,needTime: 0,needYield: 0,saveState: 0,restoreState: 0,isEOF: 1,invalidates: 0,keyPattern: {key: 1},indexName: key,isMultiKey: false,multiKeyPaths: {key: []},isUnique: false,isSparse: false,isPartial: false,indexVersion: 2,direction: forward,indexBounds: {key: [[\factor:Age\, \factor:Age\]]},keysExamined: 1,seeks: 1,dupsTested: 0,dupsDropped: 0,seenInvalidated: 0}}},ok: 1,operationTime: {$timestamp: {t: 1706014465, i: 1}},queryPlanner: {plannerVersion: 1,namespace: corpus.mds_factors,indexFilterSet: false,parsedQuery: {key: {$eq: factor:Age}},winningPlan: {stage: FETCH,inputStage: {stage: IXSCAN,keyPattern: {key: 1},indexName: key,isMultiKey: false,multiKeyPaths: {key: []},isUnique: false,isSparse: false,isPartial: false,indexVersion: 2,direction: forward,indexBounds: {key: [[\factor:Age\, \factor:Age\]]}}},rejectedPlans: []},serverInfo: {host: mongodb-replicaset-2,port: 27017,version: 3.6.20,gitVersion: 39c200878284912f19553901a6fea4b31531a899}}
]解读
winningPlan表示获胜的计划即数据库经过一系列评估后选择的最优计划stageCOLLSCAN表示全表扫描IXSCAN表示索引扫描executionStats描述执行的过程信息。nReturned指返回结果条数而totalDocsExamined表明整个过程扫描多少条记录
参考
MongoDB进阶与实战微服务整合、性能优化、架构管理MongoDB权威指南difference-between-createindex-and-ensureindex-in-java-using-mongodb