• 浅尝辄止MongoDB:优化


    目录

    一、查询分析器

    1. 启用查询分析器

    2. 禁用查询分析器

    3. 查找慢查询

    4. 增大分析器集合的大小

    二、explain

    三、使用索引优化查询

    1. 管理索引

    2. 索引选择三步法

    3. 指定索引选项

    4. 使用hint()

    5. 使用索引过滤器

    一、查询分析器
    1. 启用查询分析器
    > use test;
    switched to db test
    > db.setProfilingLevel(1);
    { "was" : 0, "slowms" : 100, "sampleRate" : 1, "ok" : 1 }
    2. 禁用查询分析器
    > use test;
    switched to db test
    > db.setProfilingLevel(0);
    { "was" : 1, "slowms" : 100, "sampleRate" : 1, "ok" : 1 }
    >
    # 只记录执行超过半秒钟的查询:

    > use test;
    switched to db test
    > db.setProfilingLevel(1,500);
    { "was" : 1, "slowms" : 500, "sampleRate" : 1, "ok" : 1 }
            对于分析级别1,可以提供以毫秒为单位的最大查询执行时间。如果查询的执行时间超过该设置,它将被分析,然后记录下来;否则,它将被忽略。这种方式提供了与MySQL慢查询日志相同的功能。若将分析级别设置为2,可为所有查询启用分析器:

    > use test;
    switched to db test
    > db.setProfilingLevel(2);
    { "was" : 2, "slowms" : 100, "sampleRate" : 1, "ok" : 1 }
    3. 查找慢查询
    db.system.profile.find();
            每条记录返回的字段含义和作用:

    op:操作类型,可以是query、insert、update、command或delete。
    query:正在运行的查询。
    ns:查询所在的完整命名空间。
    ntoreturn:返回文档的数目。
    nscanned:为返回该文档而扫描的索引条目数目。
    ntoskip:被忽略的文档数目。
    keyUpdates:该查询更新的索引键数目。
    numYields:该查询为其它查询让出锁的次数。
    lockStats:数据库花费在获取读写锁上的毫秒数。
    nreturned:返回文档的数目。
    responseLength:响应的字节长度。
    millis:执行查询所花费的毫秒数。
    ts:以UTC格式显示查询执行时的时间戳。
    client:运行该查询的客户端连接信息。
    user:运行该操作的用户。
            查询所有执行时间长于10毫秒的查询,然后按执行时间对结果进行降序排序:

    db.system.profile.find({millis:{$gt:10}}).sort({millis:-1});
    4. 增大分析器集合的大小
    use test;
    db.setProfilingLevel(0);
    db.system.profile.drop();
    db.createCollection( "system.profile", { capped: true, size: 50 * 1024 * 1024 } );
    db.setProfilingLevel(2);
    二、explain
    > db.products.find().explain(true)
    {
        "queryPlanner" : {
            "plannerVersion" : 1,
            "namespace" : "test.products",
            "indexFilterSet" : false,
            "parsedQuery" : {
                
            },
            "winningPlan" : {
                "stage" : "COLLSCAN",
                "direction" : "forward"
            },
            "rejectedPlans" : [ ]
        },
        "executionStats" : {
            "executionSuccess" : true,
            "nReturned" : 3,
            "executionTimeMillis" : 0,
            "totalKeysExamined" : 0,
            "totalDocsExamined" : 3,
            "executionStages" : {
                "stage" : "COLLSCAN",
                "nReturned" : 3,
                "executionTimeMillisEstimate" : 0,
                "works" : 5,
                "advanced" : 3,
                "needTime" : 1,
                "needYield" : 0,
                "saveState" : 0,
                "restoreState" : 0,
                "isEOF" : 1,
                "invalidates" : 0,
                "direction" : "forward",
                "docsExamined" : 3
            },
            "allPlansExecution" : [ ]
        },
        "serverInfo" : {
            "host" : "hdp4",
            "port" : 27017,
            "version" : "4.0.2",
            "gitVersion" : "fc1573ba18aee42f97a3bb13b67af7d837826b47"
        },
        "ok" : 1
    }
    >
            explain()以下字段:

    queryPlanner:执行查询的细节,包括计划的细节。
    queryPlanner.indexFilterSet:表明是否使用索引过滤器来实现这个查询。
    queryPlanner.parsedQuery:正在运行的查询。这是查询修改后的形式,显示了如何在内部评估它。
    queryPlanner.winningPlan:被选中来执行查询的计划。
    executionStats.keysExamined:表示为找到查询中的所有对象二扫描的索引条目数。
    executionStats.docsExamined:显示实际扫描的对象数量,而不仅是它们的索引条目。
    executionStats.nReturned:显示游标上的条目数量(即返回的条目数量)。
    executionStages:提供执行计划的细节。
    serverInfo:执行该查询的服务器。
            indexFilterSet表示没有使用索引;COLLSCAN表示集合扫描。如果docsExamined显著高于nReturned,那么查询可能需要添加索引。

    三、使用索引优化查询
    1. 管理索引
    MongoDB的索引用于查询(find、findOne)和排序。如果倾向于在集合中大量使用排序,那么应该根据排序的需求添加索引。
    索引最好用在主要为读访问的集合中。如果集合中有过多的索引,它们有可能会对写操作的性能造成负面影响。
    目前每个集合最多可以拥有64个索引。
    一个查询中只会使用一个索引,所以添加许多小索引通常并不会改善查询性能。复合索引提供了一种减少集合中索引数目的方法,它允许将多个字段结合在一起创建一个索引,所以应该尽量使用符合索引。
    除非数据项的列表和排序与索引结构匹配,否则排序不利用复合索引。
    (1)显示索引

    db.posts.getIndexes();
    (2)创建简单索引

    db.posts.createIndex({Tags:1});
    db.posts.createIndex({Tags:-1});
    db.posts.createIndex({"comments.count":1});
    # 查询多值索引
    db.posts.find({Tags:{$all: ['sailor', 'moon']}});
    (3)创建复合索引

    db.articles.find({author:{name: 'joe', email: 'joe@blogger.com'}));
    db.posts.createIndex({"author.name":1, "author.email":1});
    (4)删除索引

    # 删除一个集合上的所有索引
    db.posts.dropIndexes();
    # 删除单个索引(对应于createIndex()函数创建索引的语法)
    db.posts.dropIndex({"author.name":1, "author.email":1});
    (5)重建索引

    # 重建一个集合上的所有索引,nIndexesWas与nIndexes应该相同
    db.posts.reIndex();
    2. 索引选择三步法
    (1)相等测试:按任意顺序把所有相等测试的字段添加到复合索引中。
    (2)排序字段:(只有存在多个排序字段,升序/降序才重要)在索引中添加排序字段,其顺序和方向与查询的排序相同。
    (3)范围过滤器:首先,为基数最低的字段添加范围过滤器(集合中不同的值最少),接着添加基数次低的范围过滤器,直到基数最高的范围过滤器为止。

            如果相等测试或范围过滤器字段没有选择性,就可以省略它们,以减少索引的大小。经验法则是,如果字段没有过滤掉集合中至少90%的文档,就最好在索引中省略它。如果集合上有几个索引,就可能需要提示MongoDB使用正确的索引。

    3. 指定索引选项
    (1)后台创建索引

    db.posts.createIndex({author:1}, {background:true});

    # 终止索引进程
    db.currentOp();
    db.killOp(<opid>);
    (2)创建唯一索引

    db.posts.createIndex({author:1}, {unique:true});
    (3)创建稀疏索引

    db.posts.createIndex({author:1}, {sparse:true});
    (4)创建部分(条件)索引

    db.restaurants.createIndex(
       { name: 1 },
       { partialFilterExpression: { cost: { $gt: 10 } } } )
    (5)TTL索引

    db.comments.createIndex({ts:1},{ expireAfterSeconds: 2419200});
    date = new Date(new Date().getTime()-2419200000);
    db.comments.insert({ "author" : "test", "body" : "foo", "ts" : date, "tags" : [] }); 
    db.comments.find();
    # 等待一分钟,文档将被自动删除
    (6)文本索引

    db.posts.createIndex( { body: "text" } );
    db.posts.find({ "$text" : { $search: "MongoDB" } });
    db.posts.find({ "$text" : { $search: "MongoDB", $caseSensitive : true } });
    4. 使用hint()
    db.posts.createIndex({"author.name":1, "author.email":1});
    db.posts.find({author:{name:'joe', email: 'joe@mongodb.com'}}).hint({"author.name":1,"author.email":1});
    # 不使用任何索引
    db.posts.find({author:{name: 'joe', email: 'joe@mongodb.com'}}).hint({$natural:1});
    5. 使用索引过滤器
    db.runCommand(
        {
            planCacheSetFilter: "stuff",
            query: {letter : {$gt : "B"}, shape : "circle"},
            sort: {number:1},
            projection: { },
            indexes: [ { letter:1, shape:1} ]
        }
    );

    db.runCommand( { planCacheListFilters:"stuff"});

    db.runCommand(
        {
            planCacheClearFilters : "stuff",
            query: {letter : {$gt : "B"}, shape : "circle"},
            sort: {number:1},
            projection: { },
            indexes: [ { letter:1, shape:1} ]
        }
    );
    ————————————————
    版权声明:本文为CSDN博主「wzy0623」的原创文章
    原文链接:https://blog.csdn.net/wzy0623/java/article/details/83060759

  • 相关阅读:
    Swift try try! try?使用和区别
    Sitemesh 3 配置和使用(最新)
    idea + mybatis generator + maven 插件使用
    (五)Hololens Unity 开发之 手势识别
    (四)Hololens Unity 开发之 凝视系统
    (二)Hololens Unity 开发入门 之 Hello HoloLens~
    (三)Hololens Unity 开发之 语音识别
    (一)Hololens Unity 开发环境搭建(Mac BOOTCAMP WIN10)
    iOS多线程技术方案
    基于OpenSSL的RSA加密应用(非算法)
  • 原文地址:https://www.cnblogs.com/wangyu19900123/p/12659752.html
Copyright © 2020-2023  润新知