索引
MongoDB 的索引是基于 B-tree
数据结构及对应算法形成的。_id默认会创建索引
网络异常,图片无法展示
|
索引类型
单列索引
除了 MongoDB 定义的 _id 索引之外,MongoDB 还支持在文档的单个字段上创建用户定义的升序/降序索引。
网络异常,图片无法展示
|
>db.collection.createlndex ( { source: 1 } ) //1 为升序,-1 为降序
复合索引
MongoDB 也支持复合索引,并且复合索引的规则和MySQL基本一致。复合索引中列出的字段顺序具有重要意义。例如,如果复合索引由 { userid: 1, score: -1 } 组成,则索引首先按userid正序排序,然后在每个userid的值内,再在按score倒序排序。
网络异常,图片无法展示
|
>db.collection.createIndex ({ "score": -1, "userid": 1 })
多键索引
若要为包含数组的字段建立索引,MongoDB 会为数组中的每个元素创建索引键。这些多键值索引支持对数组字段的高效查询
网络异常,图片无法展示
|
索引新增删除
- 创建索引
db.collection.createIndex( { name: -1 } ) db.user.getIndexes() [ { v: 2, key: { _id: 1 }, name: '_id_' }, { v: 2, key: { name: 1 }, name: 'name_1' } ] Atlas atlas-119lob-shard-0 [primary] test> db.user.createIndex({name: 1},{name:"idx_name"}) idx_name Atlas atlas-119lob-shard-0 [primary] test> db.user.getIndexes() [ { v: 2, key: { _id: 1 }, name: '_id_' }, { v: 2, key: { name: 1 }, name: 'idx_name' } ]
- 删除索引
db.user.dropIndexes("name_1")
执行计划
explain有三种模式,分别是:queryPlanner、executionStats、allPlansExecution。
- queryPlanner:输出索引的候选索引,包括最优索引及其执行stage过程(winningPlan)+其他非最优候选索引及其执行stage过程
- executionStats:相比queryPlanner参数,executionStats会记录查询优化器根据所选最优索引执行SQL的整个过程信息,会真正执行整个SQL。
- allPlansExecution:和executionStats类似,只是多了所有候选索引的执行过程
新增10000条测试数据
for (let i = 1; i <= 500000; i++) db.item.insertOne({_id:i, item_id: "10010_" + i, item_order: "P1HNHN" + i, test:"test_"+i+"TES"})
Atlas atlas-119lob-shard-0 [primary] order> db.item.find({item_id:"10010_38976"}).explain("executionStats") { explainVersion: '1', queryPlanner: { namespace: 'order.item', indexFilterSet: false, parsedQuery: { item_id: { '$eq': '10010_38976' } }, maxIndexedOrSolutionsReached: false, maxIndexedAndSolutionsReached: false, maxScansToExplodeReached: false, winningPlan: { stage: 'COLLSCAN', filter: { item_id: { '$eq': '10010_38976' } }, direction: 'forward' }, rejectedPlans: [] }, executionStats: { executionSuccess: true, nReturned: 1, executionTimeMillis: 23, totalKeysExamined: 0, totalDocsExamined: 50000, executionStages: { stage: 'COLLSCAN', filter: { item_id: { '$eq': '10010_38976' } }, nReturned: 1, executionTimeMillisEstimate: 2, works: 50002, advanced: 1, needTime: 50000, needYield: 0, saveState: 50, restoreState: 50, isEOF: 1, direction: 'forward', docsExamined: 50000 } }, command: { find: 'item', filter: { item_id: '10010_38976' }, '$db': 'order' }, serverInfo: { host: 'cluster0-shard-00-02.fdv5c.mongodb.net', port: 27017, version: '5.0.8', gitVersion: 'c87e1c23421bf79614baf500fda6622bd90f674e' }, serverParameters: { internalQueryFacetBufferSizeBytes: 104857600, internalQueryFacetMaxOutputDocSizeBytes: 104857600, internalLookupStageIntermediateDocumentMaxSizeBytes: 16793600, internalDocumentSourceGroupMaxMemoryBytes: 104857600, internalQueryMaxBlockingSortMemoryUsageBytes: 33554432, internalQueryProhibitBlockingMergeOnMongoS: 0, internalQueryMaxAddToSetBytes: 104857600, internalDocumentSourceSetWindowFieldsMaxMemoryBytes: 104857600 }, ok: 1, '$clusterTime': { clusterTime: Timestamp(1, 1651821606), signature: { hash: Binary(Buffer.from("9250e56618dba0aacb504c846045c8e534adb68f", "hex"), 0), keyId: Long("7066952799589761026") } }, operationTime: Timestamp(1, 1651821606) }
在item_id上创建索引
db.item.createIndex ({ "item_id": 1},{"name":"idx_item_id" })
Atlas atlas-119lob-shard-0 [primary] order> db.item.find({item_id:"10010_38976"}).explain("executionStats") { explainVersion: '1', queryPlanner: { namespace: 'order.item', indexFilterSet: false, parsedQuery: { item_id: { '$eq': '10010_38976' } }, maxIndexedOrSolutionsReached: false, maxIndexedAndSolutionsReached: false, maxScansToExplodeReached: false, winningPlan: { stage: 'FETCH', inputStage: { stage: 'IXSCAN', keyPattern: { item_id: 1 }, indexName: 'idx_item_id', isMultiKey: false, multiKeyPaths: { item_id: [] }, isUnique: false, isSparse: false, isPartial: false, indexVersion: 2, direction: 'forward', indexBounds: { item_id: [ '["10010_38976", "10010_38976"]' ] } } }, rejectedPlans: [] }, executionStats: { executionSuccess: true, nReturned: 1, executionTimeMillis: 0, 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, 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, keyPattern: { item_id: 1 }, indexName: 'idx_item_id', isMultiKey: false, multiKeyPaths: { item_id: [] }, isUnique: false, isSparse: false, isPartial: false, indexVersion: 2, direction: 'forward', indexBounds: { item_id: [ '["10010_38976", "10010_38976"]' ] }, keysExamined: 1, seeks: 1, dupsTested: 0, dupsDropped: 0 } } }, command: { find: 'item', filter: { item_id: '10010_38976' }, '$db': 'order' }, serverInfo: { host: 'cluster0-shard-00-02.fdv5c.mongodb.net', port: 27017, version: '5.0.8', gitVersion: 'c87e1c23421bf79614baf500fda6622bd90f674e' }, serverParameters: { internalQueryFacetBufferSizeBytes: 104857600, internalQueryFacetMaxOutputDocSizeBytes: 104857600, internalLookupStageIntermediateDocumentMaxSizeBytes: 16793600, internalDocumentSourceGroupMaxMemoryBytes: 104857600, internalQueryMaxBlockingSortMemoryUsageBytes: 33554432, internalQueryProhibitBlockingMergeOnMongoS: 0, internalQueryMaxAddToSetBytes: 104857600, internalDocumentSourceSetWindowFieldsMaxMemoryBytes: 104857600 }, ok: 1, '$clusterTime': { clusterTime: Timestamp(2, 1651821695), signature: { hash: Binary(Buffer.from("035c24b6cc83e5d1d5bca97befb43a2c2fc30605", "hex"), 0), keyId: Long("7066952799589761026") } }, operationTime: Timestamp(2, 1651821695) }
事务
什么是writeConcern?
writeConcern 决定一个写操作落到多少个节点上才算成功。writeConcern 的取值包括:
- 0:发起写操作,不关心是否成功;
- 1~集群最大数据节点数:写操作需要被复制到指定节点数才算成功;
- majority:写操作需要被复制到大多数节点上才算成功。
发起写操作的程序将阻塞到写操作到达指定的节点数为止
网络异常,图片无法展示
|
majority
网络异常,图片无法展示
|
副本集
MongoDB的副本集主要用于实现服务的高可用。
- 数据写入时将数据迅速复制到其他节点上
- 在Primary节点出现故障后自动选举一个Secondary节点作为Primary
网络异常,图片无法展示
|
Golang操作MongoDB
var client *mongo.Client type Item struct { ItemId string `bson:"item_id"` ItemOrder string `bson:"item_order"` Test string `bson:"test"` UpdateTime string `bson:"update_time"` } func main() { initDB() collection := client.Database("order").Collection("item") result, err := collection.InsertOne(context.TODO(), &Item{ ItemId: "test_item_id", ItemOrder: "test_item_order", Test: "test_test", UpdateTime: time.Now().Format("2006-01-02 15:04:05"), }) if err != nil{ log.Fatal(err) } fmt.Println(result.InsertedID) // find() } func find(){ initDB() collection := client.Database("order").Collection("item") cursor, err := collection.Find(context.TODO(), bson.D{{"itemid", "test_item_id"}}) if err != nil { log.Fatal(err) } defer cursor.Close(context.TODO()) for cursor.Next(context.TODO()) { item := &Item{} err := cursor.Decode(item) if err != nil { log.Fatal(err) } fmt.Println(item) } } func initDB() { clientOptions := options.Client().ApplyURI(url) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() c, err := mongo.Connect(ctx, clientOptions) if err != nil { log.Fatal(err) } err3 := c.Ping(ctx, nil) if err3 != nil { log.Fatal(err3) } fmt.Println("mongodb connected") client = c }