浅尝辄止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

浅尝辄止MongoDB:优化

上一篇:orcl数据库自定义函数--金额小写转大写


下一篇:window安装MYSQL出错:a windows service with the name MYSQL already...service.