kagxin / blog

个人博客:技术、随笔、生活
https://github.com/kagxin/blog/issues
7 stars 0 forks source link

mongodb 索引注意事项 #52

Open kagxin opened 4 years ago

kagxin commented 4 years ago

mongodb 索引注意事项

这篇文章里使用的pymongo,对mongodb的数据和索引进行操作。

生成测试数据

生成一个测试用的集合,文档数量为1000000个

from pymongo import MongoClient
from mongo import m
import random
import datetime

mongo_uri = 'mongodb://root:root@localhost:27017'
connection = MongoClient(mongo_uri)
m = connection['demo']

for i in range(1000000):
    t = {
        'i': i,
        'username': 'username' + str(i),
        'age': random.randint(1, 100),
        'created': datetime.datetime.now()
    }
    m.users.insert(t)

m.users.insert({
        'i': 101,

        'username': 'username' + str(101),
        'age': 20,
        'created': datetime.datetime.now()
    })

mongodb几个注意点

## 两个索引 age和created
m.get_collection('users').create_index([
    ('age', pymongo.ASCENDING)  
])
m.get_collection('users').create_index([
    ('created', pymongo.ASCENDING)
])

## 范围查询 created和age
m.get_collection('users').find(
    {'created': {'gte': (datetime.datetime.now() - datetime.timedelta(days=1))}, 'age': {'gt': 18}}).explain()
//explain 结果, 并未使用created和age上的两个索引,而是只是用了created上的索引
/* 1 */
{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "demo.users",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "$and" : [ 
                {
                    "age" : {
                        "$eq" : {
                            "gt" : 18.0
                        }
                    }
                }, 
                {
                    "created" : {
                        "$eq" : {
                            "gte" : ISODate("2019-11-18T15:51:55.888Z")
                        }
                    }
                }
            ]
        },
        "queryHash" : "3E2E5ACC",
        "planCacheKey" : "D9F6B0E9",
        "winningPlan" : {
            "stage" : "FETCH",
            "filter" : {
                "age" : {
                    "$eq" : {
                        "gt" : 18.0
                    }
                }
            },
            "inputStage" : {
                "stage" : "IXSCAN",
                "keyPattern" : {
                    "created" : 1
                },
                "indexName" : "created_1",
                "isMultiKey" : false,
                "multiKeyPaths" : {
                    "created" : []
                },
                "isUnique" : false,
                "isSparse" : false,
                "isPartial" : false,
                "indexVersion" : 2,
                "direction" : "forward",
                "indexBounds" : {
                    "created" : [ 
                        "[{ gte: new Date(1574092315888) }, { gte: new Date(1574092315888) }]"
                    ]
                }
            }
        },
        "rejectedPlans" : [ 
           ...
        ]
    },
    "serverInfo" : {
        ...
    },
    "ok" : 1.0
}
## 这种情况下最好是创建复合索引,这样mongodb会使用username_age这个复合索引
m.get_collection('users').create_index([
    ('username', pymongo.ASCENDING),
    ('age', pymongo.ASCENDING)
])
m.get_collection('users').find({}).sort([('username', pymongo.ASCENDING), ('age', pymongo.DESCENDING)]).explain()

## 当使用 username和age进行一个正向,一个逆向排序时
## ('username', pymongo.ASCENDING),('age', pymongo.ASCENDING) 这根索引将不再有效mongodb无法使用它进行排序

m.get_collection('users').create_index([
    ('username', pymongo.ASCENDING),
    ('age', pymongo.ASCENDING)
])

## 创建这样的索引是正确的选择('username', pymongo.ASCENDING),('age', pymongo.DESCENDING)

m.get_collection('users').create_index([
    ('username', pymongo.ASCENDING),
    ('age', pymongo.DESCENDING)
])

ref

https://github.com/kagxin/blog/issues/52 https://docs.mongodb.com/manual/reference/operator/meta/explain/index.html https://docs.mongodb.com/manual/indexes/ 《mongodb权威指南》

kagxin commented 4 years ago

一次添加TTL索引的监控情况

db.getCollection('device_data').createIndex( { "date_time": 1 }, { expireAfterSeconds: 604800, background:true} )

添加了一个TTL索引,集合文档数量2200万减到950万。(添加之前删除了原有的date_time上的一个普通单列索引)

image image image