mongodb之使用explain和hint性能分析和优化

http://www.cnblogs.com/huangxincheng/p/5737222.html

  当你第一眼看到explain和hint的时候,第一个反应就是mysql中所谓的这两个关键词,确实可以看出,这个就是在mysql中借鉴过来的,既然是借鉴

过来的,我想大家都知道这两个关键字的用处,话不多说,速速观看~~~

 

一:explain演示

1.  构建数据

为了方便演示,我需要create ten data to inventory,而且还是要在no index 的情况下,比如下面这样:

复制代码
 1 db.inventory.insertMany([
 2 { "_id" : 1, "item" : "f1", type: "food", quantity: 500 },
 3 { "_id" : 2, "item" : "f2", type: "food", quantity: 100 },
 4 { "_id" : 3, "item" : "p1", type: "paper", quantity: 200 },
 5 { "_id" : 4, "item" : "p2", type: "paper", quantity: 150 },
 6 { "_id" : 5, "item" : "f3", type: "food", quantity: 300 },
 7 { "_id" : 6, "item" : "t1", type: "toys", quantity: 500 },
 8 { "_id" : 7, "item" : "a1", type: "apparel", quantity: 250 },
 9 { "_id" : 8, "item" : "a2", type: "apparel", quantity: 400 },
10 { "_id" : 9, "item" : "t2", type: "toys", quantity: 50 },
11 { "_id" : 10, "item" : "f4", type: "food", quantity: 75 }]);
复制代码

 

2. 无索引查询

db.inventory.find(
   { quantity: { $gte: 100, $lte: 200 } }
).explain("executionStats")

 

从上图中,我们看到了三个圈圈,这些都是我们在find中非常重要的信息,具体信息解释如下:

 

<1>COLLSCAN

      这个是什么意思呢? 如果你仔细一看,应该知道就是CollectionScan,就是所谓的“集合扫描”,对不对,看到集合扫描是不是就可以直接map到

数据库中的table scan/heap scan呢??? 是的,这个就是所谓的性能最烂最无奈的由来。

<2> nReturned

      这个很简单,就是所谓的numReturned,就是说最后返回的num个数,从图中可以看到,就是最终返回了三条。。。

<3> docsExamined

     那这个是什么意思呢??就是documentsExamined,检查了10个documents。。。而从返回上面的nReturned。。。

 

ok,那从上面三个信息中,我们可以得出,原来我examine 10 条数据,最终才返回3条,说明做了7条数据scan的无用功,那么这个时候问题就来了,

如何减少examine的documents。。。

 

完整的plans如下:

复制代码
/* 1 */
{
    "queryPlanner" : {
        "plannerVersion" : 1,
        "namespace" : "datamip.inventory",
        "indexFilterSet" : false,
        "parsedQuery" : {
            "$and" : [ 
                {
                    "quantity" : {
                        "$lte" : 200.0
                    }
                }, 
                {
                    "quantity" : {
                        "$gte" : 100.0
                    }
                }
            ]
        },
        "winningPlan" : {
            "stage" : "COLLSCAN",
            "filter" : {
                "$and" : [ 
                    {
                        "quantity" : {
                            "$lte" : 200.0
                        }
                    }, 
                    {
                        "quantity" : {
                            "$gte" : 100.0
                        }
                    }
                ]
            },
            "direction" : "forward"
        },
        "rejectedPlans" : []
    },
    "executionStats" : {
        "executionSuccess" : true,
        "nReturned" : 3,
        "executionTimeMillis" : 1,
        "totalKeysExamined" : 0,
        "totalDocsExamined" : 10,
        "executionStages" : {
            "stage" : "COLLSCAN",
            "filter" : {
                "$and" : [ 
                    {
                        "quantity" : {
                            "$lte" : 200.0
                        }
                    }, 
                    {
                        "quantity" : {
                            "$gte" : 100.0
                        }
                    }
                ]
            },
            "nReturned" : 3,
            "executionTimeMillisEstimate" : 0,
            "works" : 12,
            "advanced" : 3,
            "needTime" : 8,
            "needYield" : 0,
            "saveState" : 0,
            "restoreState" : 0,
            "isEOF" : 1,
            "invalidates" : 0,
            "direction" : "forward",
            "docsExamined" : 10
        }
    },
    "serverInfo" : {
        "host" : "localhost.localdomain",
        "port" : 27017,
        "version" : "3.2.8",
        "gitVersion" : "ed70e33130c977bda0024c125b56d159573dbaf0"
    },
    "ok" : 1.0
}
复制代码

 

3. 使用single field 加速查找

   知道前因后果之后,我们就可以进行针对性的建立索引,比如在quality字段之上,如下:

db.inventory.createIndex({ quantity: 1})

db.inventory.find(
   { quantity: { $gte: 100, $lte: 200 } }
).explain("executionStats")

好了,这时候就有意思了,当我们执行完createindex之后,再次explain,4个重要的parameters就漂下来了:

<1> IXSCAN

       这个时候再也不是所谓的COLLSCAN了,而是IndexScan,这就说明我们已经命中索引了。

<2> nReturned,totalDocsExamined,totalKeysExamined

       从图中可以看到三个参数都是3,这就说明我们的mongodb查看了3个key,3个document,返回3个文档,这个就是所谓的高性能所在,对吧。

 

二:hint演示

    说到hint,我想大家也是知道的,很好玩的一个东西,就是用来force mongodb to excute special index,对吧,为了方便演示,我们做两组复合索

引,比如这次我们在quality和type上构建一下:

 

building完成之后,我们故意这一个这样的查询,针对quantity是一个范围,而type是一个定值的情况下,我们force mongodb去使用quantity开头

的复合索引,从而强制mongodb give up 那个以{type:1,quantity:1}的复合索引,很有意思哦,比如下图:

从图中,可以看到,我们检查了6个keys,而从最终找到了2个文档,现在我们就知道了,2和6之间还是有不足的地方等待我们去优化了,对吧,下面

我们不hint来看一下mongodb的最优的plan是怎么样的。

 

再看上面的图,你应该明白了,mongodb果然执行了那个最优的plan,是不是很好玩,好了,本篇就说到这里,希望对你有帮助~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MongoDB性能优化是指通过一系列技术手段来提升MongoDB数据库的读写效率、响应速度和吞吐量。下面是一些常见的MongoDB性能优化方法: 1. 索引优化使用合适的索引可以加速查询操作。在选择索引字段时,应根据查询的频率和字段的选择性来进行考虑。避免创建过多的索引,因为过多的索引会增加数据写入和更新的开销。 2. 查询优化使用合适的查询语句和操作符可以减少数据扫描的量。避免使用全表扫描操作,尽量利用索引进行查询。 3. 数据模型优化:合理设计数据模型可以提升数据库的性能。将经常一起查询的数据放在同一个集合中,避免频繁的跨集合查询。 4. 分片集群优化:对于大规模数据集,可以使用分片集群来提高性能和可伸缩性。通过合理划分数据和配置分片,可以实现负载均衡和并行查询。 5. 预分配空间:在写入大量数据之前,可以预先为集合或数据库分配足够的存储空间,避免频繁的扩容操作对性能造成影响。 6. 配置参数优化:根据系统硬件和工作负载的特点,调整MongoDB的配置参数,如缓存大小、线程数等,以获得更好的性能表现。 7. 使用复制集和副本集:通过配置复制集和副本集,可以提高数据的可用性和读取性能。 8. 批量操作和异步写入:通过批量操作和异步写入方式可以提高写入性能。例如,使用Bulk Write API进行批量插入、更新和删除操作;启用Write Concern的"unacknowledged"模式,将写入操作异步化。 9. 监控和调优:定期监控数据库的性能指标,如QPS、响应时间、磁盘使用率等,及时发现并解决潜在的性能问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值