TrimFields出现别名消失问题

背景:在工作中遇到了当使用select * from view时,若字段取了别名,当对它进行了列裁剪之后,会出现别名消失的情况

问题定位:

1.首先介绍一下列裁剪,假设a表有字段a、b、c,b表有字段d、e、f,将a和b表做Join。但最后我们查询所需要的字段只有a、b、d,

那么我们可以在Join之前,只获取a、b、d字段和join条件的字段即可,不需要获取更多的数据。

2.那么为什么会出现别名消失?

因为我们查询的是全字段,即所有的数据都可以从Project的子节点中获得,那么该Project字段从获取全部数据的角度来说 确实没有存在的必要。

calcite中可以看到在列裁剪时,会构造一个裁剪完成的Project算子,该算子就是需要用到哪些字段则构造那些字段的一个Project

但是进入relBuilder.project()方法中,可以看到传入了当前的rowType即包含别名的rowType。在该方法中也做了判断,子算子的rowType和传入的rowType是否相同,按理说会在其中进行一个别名的判断,若有别名则不消除该全字段的Project。但是Calcite并没有这么做,所以我认为这可能是一个小bug或者也可能是我理解错误。

解决方案:

由上述可知,别名消除的根本原因是因为对于全字段的Project,会被认为没有必要存在,所以我认为的一种解法就是重写Calcite中的

public TrimResult trimFields(Project project, ImmutableBitSet fieldsUsed, Set extraFields) 

如果使用到的字段是子算子中的全字段,那么就不要消除该字段,继续递归下去。

@Override
    public TrimResult trimFields(Project project, ImmutableBitSet fieldsUsed, Set<RelDataTypeField> extraFields)
    {
        TrimResult result = super.trimFields(project, fieldsUsed, extraFields);
        // if project fieldsUsed equals fieldsCount of child, then do not remove current project
        if (result.left.getRowType().getFieldCount() == fieldsUsed.cardinality()) {
            result = result(project, result.right);
        }
        return result;
    }

第二种解法就是修改Calcite的源代码,在两个rowType中名字不同时,会保留Project(当然真正的过程时再生成一个和原先Project相同的Project)

 拓展:下面再浅谈一下TrimFields的基本原理,便于更好理解以上解决方案的原因。

以一个简单的例子来讲述这个过程:

假设当前的查询结构如下:

LogicalProject[alias,b,c,d]
    LogicalProject[a,b,c,d]
        Scan[table1]

首先第一步:

传入当前的根节点,获取它使用到了哪些字段,并通过dispatchTrimFields()进行分发,对不同的节点会有不同的处理

第二步:

分发到Project算子,这是一个递归的操作,递归前会分析当前算子获取它用到的字段,然后再进入下一个算子。

最后再自底向上进行判断,以上例子,scan上方的Project算子,选中Scan全字段因此会变成如下

LogicalProject[alias,b,c,d]
    
        Scan[table1]

再递归向上找到最顶层的Project,也是全字段的Project,因此最后就会变成

Scan[table1]

所以现在回顾我们的解法,当递归到底,再向上时判断是否全字段,若是全字段则可能会出现别名消失情况,因此跳过。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值