Mongodb的逻辑优化过程
2017-10-07 16:53
127 查看
逻辑优化过程在关系型数据库里面, 是一个非常复杂的过程, 幸运的是, 在Mongodb里面, 到目前为止, 相对来说, 其实现还是比较简单的。该过程主要通过 CanonicalQuery 类来实现。
该过程主要包含三个方面的优化:
1、Normoralize tree;
2、sort tree;
3、 validate tree;
我们分别来看看这3个方面的优化的实现。
此时的MatchExpression, 应该为如下的结构:
经过Normalize以后, 应该把AND of AND类型的节点提升到父节点的兄弟节点, 如下:
从上面两幅图的对比, 比较直观的看到, 节点数变少, 层数也变少了。 我们看一下代码:
这里, 采用了递归的调用方式, 针对and,or, not,elemMatch 4中操作符进行, not和elemMatch 是针对其subnode 调用normalizeTree, and和or 递归的吧子节点提升为父节点的兄弟节点。
1) operator type (MatchExpression::MatchType)
2) path name (MatchExpression::path())
3) sort order of children
4) number of children (MatchExpression::numChildren())
代码的实现就比较简单, 按照上面的4中比较方式以及优先级。
该过程主要包含三个方面的优化:
1、Normoralize tree;
2、sort tree;
3、 validate tree;
我们分别来看看这3个方面的优化的实现。
1. Normoralize tree
该过程主要是针对 AND, OR的子对象的类型也是AND, OR的情况, 把他们从子节点提升到父节点。 已如下的AND的为例子:
db.inventory.find( { $and : [ { $and : [ { price : 0.99 }, { count : 99 } ] }, { $and : [ { sale : true }, { qty : 20} ] } ] } )
此时的MatchExpression, 应该为如下的结构:
经过Normalize以后, 应该把AND of AND类型的节点提升到父节点的兄弟节点, 如下:
从上面两幅图的对比, 比较直观的看到, 节点数变少, 层数也变少了。 我们看一下代码:
MatchExpression* CanonicalQuery::normalizeTree(MatchExpression* root) { // root->isLogical() is true now. We care about AND, OR, and NOT. NOR currently scares us. if (MatchExpression::AND == root->matchType() || MatchExpression::OR == root->matchType()) { // We could have AND of AND of AND. Make sure we clean up our children before merging // them. // UNITTEST 11738048 for (size_t i = 0; i < root->getChildVector()->size(); ++i) { (*root->getChildVector())[i] = normalizeTree(root->getChild(i)); } // If any of our children are of the same logical operator that we are, we remove the // child's children and append them to ourselves after we examine all children. std::vector<MatchExpression*> absorbedChildren; for (size_t i = 0; i < root->numChildren();) { MatchExpression* child = root->getChild(i); if (child->matchType() == root->matchType()) { // AND of an AND or OR of an OR. Absorb child's children into ourself. for (size_t j = 0; j < child->numChildren(); ++j) { absorbedChildren.push_back(child->getChild(j)); } // TODO(opt): this is possibly n^2-ish root->getChildVector()->erase(root->getChildVector()->begin() + i); child->getChildVector()->clear(); // Note that this only works because we cleared the child's children delete child; // Don't increment 'i' as the current child 'i' used to be child 'i+1' } else { ++i; } } root->getChildVector()->insert( root->getChildVector()->end(), absorbedChildren.begin(), absorbedChildren.end()); // AND of 1 thing is the thing, OR of 1 thing is the thing. if (1 == root->numChildren()) { MatchExpression* ret = root->getChild(0); root->getChildVector()->clear(); delete root; return ret; } } else if (MatchExpression::NOT == root->matchType()) { // Normalize the rest of the tree hanging off this NOT node. NotMatchExpression* nme = static_cast<NotMatchExpression*>(root); MatchExpression* child = nme->releaseChild(); // normalizeTree(...) takes ownership of 'child', and then // transfers ownership of its return value to 'nme'. nme->resetChild(normalizeTree(child)); } else if (MatchExpression::ELEM_MATCH_VALUE == root->matchType()) { // Just normalize our children. for (size_t i = 0; i < root->getChildVector()->size(); ++i) { (*root->getChildVector())[i] = normalizeTree(root->getChild(i)); } } return root; }
这里, 采用了递归的调用方式, 针对and,or, not,elemMatch 4中操作符进行, not和elemMatch 是针对其subnode 调用normalizeTree, and和or 递归的吧子节点提升为父节点的兄弟节点。
2. sort tree
sort tree 主要是对MatchExpression的各个子树进行排序, 排序之后的好处就是对于index查询, 如果某个字段的index被分成了几段, 我们的查询用到其中的2段, 就可以做到对于索引的查找只需要一次就能完成。其具体的排序的顺序:1) operator type (MatchExpression::MatchType)
2) path name (MatchExpression::path())
3) sort order of children
4) number of children (MatchExpression::numChildren())
代码的实现就比较简单, 按照上面的4中比较方式以及优先级。
3. validate tree
主要是判断由MatchExpression产生的LiteParsedQuery 对象的设定是否有不正确的地方。相关文章推荐
- Mongodb使用过程中的优化原则
- 针对sql 2005优化的高性能分页存储过程
- 解密所有APP运行过程中的内部逻辑
- 优化SQL Server数据逻辑 提高查询性能
- MongoDB优化,建立索引实例及索引机制原理讲解
- Cache 优化过程中必须考虑的因素之一 Cache 优化过程中必须考虑的因素之一
- 安装MongoDB以及可视化工具adminmongo后的启动过程
- MongoDB 性能优化之索引优化
- PHP开发过程中的优化细节
- Machine Learning - WEEK 1 2 3- 线性回归 、逻辑回归、梯度下降法及其优化算法、传统方法、 Octave 入门
- Mongodb索引的优化
- 减少存储过程封装业务逻辑-web开发与传统软件开发的思维模式不同
- SQL Server 优化存储过程的七种方法
- 存储过程编写经验和优化措施
- KMP算法代码实现和优化(不太能理解具体的过程和该算法思想)
- windows系统安装mongodb以及配置过程
- 原始记录一次性能优化过程
- JVM GC调整优化过程全揭秘
- kendoGrid动态列的实现-高级查询结果展示优化过程
- MySql存储过程—5、逻辑判断,条件控制