美文网首页IT@程序员猿媛RadonDBGo
学习RadonDB源码(四)

学习RadonDB源码(四)

作者: 有财君 | 来源:发表于2019-05-18 22:09 被阅读1次

    1. 继续一下昨天的话题

    昨天我学习了查询优化器的部分内容,其实主要是起了一个提纲挈领的作用,真的内容我还没有学习。那么今天首先歪个楼,写一点Go语言相关的东西,毕竟我的目的是在学习RadonDB源码的同时学习Go语言。

    plans := planner.NewPlanTree()
        switch node.(type) {
        case *sqlparser.DDL:
            node := planner.NewDDLPlan(log, database, query, node.(*sqlparser.DDL), router)
            plans.Add(node)
        case *sqlparser.Insert:
            node := planner.NewInsertPlan(log, database, query, node.(*sqlparser.Insert), router)
            plans.Add(node)
        case *sqlparser.Delete:
            node := planner.NewDeletePlan(log, database, query, node.(*sqlparser.Delete), router)
            plans.Add(node)
        case *sqlparser.Update:
            node := planner.NewUpdatePlan(log, database, query, node.(*sqlparser.Update), router)
            plans.Add(node)
        case *sqlparser.Select:
            nod := node.(*sqlparser.Select)
            selectNode := planner.NewSelectPlan(log, database, query, nod, router)
            plans.Add(selectNode)
        case *sqlparser.Checksum:
            node := planner.NewOthersPlan(log, database, query, node, router)
            plans.Add(node)
        default:
            return nil, errors.Errorf("optimizer.unsupported.query.type[%+v]", node)
    

    首先呢,代码新建了一个PlanTree指针类型的plans。然后呢,根据不同的node类型判断分支,每一个分支里都会新建一个不同类型的Plan,然后把这个Plan放入到plans里。

    看到这里我有点恍惚了,这有点像多态啊。我们来看看NewPlanTree都干了什么:

    type Plan interface {
        Build() error
        Type() PlanType
        JSON() string
        Size() int
        Children() *PlanTree
    }
    
    // PlanTree is a container for all plans
    type PlanTree struct {
        size     int
        children []Plan
    }
    
    // NewPlanTree creates the new plan tree.
    func NewPlanTree() *PlanTree {
        return &PlanTree{
            children: make([]Plan, 0, 8),
        }
    }
    

    其实就是新建了一个Plan类型的切片放在了PlanTree里。Plan是一个接口,有了接口就能实现多态,这是我之前讲过的:

    Go语言之初识接口

    刚刚好,不管是ddl_plan还是其他的plan,都实现了这个接口,也就是说实现了多态,可以将这些plan全都放在plan类型的切片里了。

    Go的多态实现,或者说接口,我个人觉得没有Java好理解。

    2. DDL Plan在干什么

    其实DDL本无所谓什么plan,但是自从有了分库,就有了plan。
    ----周树人

    分库的情况下,一切都变得比较复杂和迷乱了。其实拨开迷雾,总能看到一丝光亮,ddl_plan其实做了这么几件事:

    • 判断几种非法操作;

    • 进行简单的语法解析和替换。

    先说几种非法操作,这个对于DBA来说还是应该知道并且烂熟于心的:

    • 不能删除shard key所在的列;

    • shard key的列不能被修改;

    • 只能在shard key所在的列上做唯一约束和主键。

    接下来要遍历所有的segment,那么又引进了一个概念叫做segment。segment看起来是个元组:

    // Segment tuple.
    type Segment struct {
        // Segment table name.
        Table string `json:",omitempty"`
        // Segment backend name.
        Backend string `json:",omitempty"`
        // key range of this segment.
        Range KeyRange `json:",omitempty"`
    }
    

    其实接下来的代码就是对这个元组中的元素进行简单的处理了:

                segTable := segment.Table
                if node.Table.Qualifier.IsEmpty() {
                    segTable = fmt.Sprintf("`%s`.`%s`", database, segTable)
                    rawQuery := strings.Replace(p.RawQuery, "`", "", 2)
                    re, _ := regexp.Compile(fmt.Sprintf(`\b(%s)\b`, table))
                    query = re.ReplaceAllString(rawQuery, segTable)
                } else {
                    segTable = fmt.Sprintf("`%s`.`%s`", database, segTable)
                    newTable := fmt.Sprintf("%s.%s", database, table)
                    rawQuery := strings.Replace(p.RawQuery, "`", "", 4)
                    re, _ := regexp.Compile(fmt.Sprintf(`\b(%s)\b`, newTable))
                    query = re.ReplaceAllString(rawQuery, segTable)
                }
    

    代码逻辑很简单,会把我们在命令行上输入的类似create之类的语句进行一些字符串上的处理,主要是格式化输出和一些字符串替换等等,就不摊开讲了,没啥意思。

                tuple := xcontext.QueryTuple{
                    Query:   query,
                    Backend: segment.Backend,
                    Range:   segment.Range.String(),
                }
                p.Querys = append(p.Querys, tuple)
    

    接下来就是把刚才格式化好的查询,拼接在query字符串中。这一步完成之后,就完成了DDLPlan的构建。

    其实,DDL的plan也没什么精彩的地方。

    这世界上本来没有ddl的执行计划,有了分库之后,便有了ddl的执行计划,其实有和没有,终究是一样的。
    ----周树人

    3. 小结

    我猜,Insert的DDL会更有意思。

    写入数据,本来是简单的事情,但是有了分库,这一切终究不再简单了。
    ----周树人

    相关文章

      网友评论

        本文标题:学习RadonDB源码(四)

        本文链接:https://www.haomeiwen.com/subject/tqlxzqtx.html