calcite在flink中的二次开发,介绍解析器与优化器

从Dinky聊聊Flink的二次开发 这几天研究了一下Dinky,确实是一款很不错的软件,功能很强大,也很实用,可以极大的方便我们flink sql的开发工作,同时他也支持其他一些主流数据库的SQL,像starrocks。Dinky号称基于Flink二次开发,没有侵入Flink,所以这一点就值得我们学习,为了了解Dinky我自己也搭建了一套Dinky环境,确实使用起来非常舒适 ,搭建过程也是比较容易,下面简单列一下搭建过程。 阅读详情

关于calcite的概念相关的内容,在我另一篇帖子
深入理解flinksql执行流程,扩展解析器实现语法的扩展

1 CodeGen

首先阐述一下 codegen:
Codegen是基于ObjectWeb ASM的低开销的java代码生成器,他可以根据预先填好的规则与条件,通过编译代码,自动生成java类
在这里插入图片描述

在递归调用各个节点 DataStreamRel 的 translateToPlan 方法时,会利用CodeGen元编程成Flink的各种算子,就相当于我们直接利用Flink的DataSet或DataStream API开发的程序。
还是以上面的Demo为例,跟踪进 DataStreamScan 的 translateToPlan 方法中,会发现相关逻辑:

  1. 首先生成 function 代码的字符串形式,并封装成 GeneratedFunction 对象;
  2. 然后使用 CodeGen 进行编译;
  3. 在需要使用 Function 的时候使用反射进行加载使用。

后续在 扩展 flink语法(如join维表)时,需要针对上述步骤,拼接生成 function 的字符串形式。
在这里插入图片描述

2 flink 语法扩展

了解完 Flink Sql 的执行流程之后,就可以针对 Flink Sql 做语法、功能上的扩展。

在Flink老版本上,Flink不支持 COUNT(DISTINCT aaa) 语法,但是如果需要对 Flink 做此功能拓展,需要结合 前面说到的 Flink Sql 执行流程,做相应修改。

修改点:

  1. 在进行 Rule 规则匹配时,放开对 Distinct 的限制
  2. DataStreamRelNode 转为 DataStream 过程中,拼接CodeGen所需的 Function String

2.1 在进行 Rule 规则匹配时,放开对 Distinct 的限制

在 DATASTREAM_OPT_RULES.DataStreamGroupWindowAggregateRule 中放开对 Distinct 的限制:
在这里插入图片描述

2.2下面附上一个 利用codegen来生成所需类的例子:

新建一个项目 ,从源码中拷贝出codegen的代码文件夹在这里插入图片描述
在配置文件中,添加好,sql的保留字,关键字,类的名字等信息,这里就不多说了,有需要的同学可以百度具体的原理技术
新建一个SqlUseFunction.java 这个就是上文中说到的function 代码的字符串形式,
在flink中,就是通过 拼装来拼装出一个类,调用codegen来进行编译得到继承抽象类SqlNode 的方法,所以在开发完的源代码中是找不到codegen相关的东西的,但实际他是参与了工作的。

package com;

import org.apache.calcite.sql.*;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.util.ImmutableNullableList;

import java.util.List;

public class SqlUseFunction extends SqlCall {

    private static final SqlSpecialOperator OPERATOR = new SqlSpecialOperator("USE FUNCTION",
            SqlKind.OTHER_FUNCTION);

    private final SqlIdentifier funcName;
    private final SqlNodeList funcProps;

    /**
     * SqlUseFunction constructor.
     *
     * @param pos sql define location
     * @param funcName function name
     * @param funcProps function property
     * */
    public SqlUseFunction(SqlParserPos pos, SqlIdentifier funcName, SqlNodeList funcProps) {
        super(pos);
        this.funcName = funcName;
        this.funcProps = funcProps;
    }

    @Override
    public void unparse(SqlWriter writer, int leftPrec, int rightPrec) {
        writer.keyword("USE FUNCTION");
        funcName.unparse(writer, leftPrec, rightPrec);
        if (funcProps != null) {
            writer.keyword("WITH");
            SqlWriter.Frame frame = writer.startList("(", ")");
            for (SqlNode c : funcProps) {
                writer.sep(",");
                c.unparse(writer, 0, 0);
            }
            writer.endList(frame);
        }
    }

    @Override
    public SqlOperator getOperator() {
        return OPERATOR;
    }

    @Override
    public List<SqlNode> getOperandList() {
        return ImmutableNullableList.of(funcName, funcProps);
    }

}

pom文件中指定好,使用fmpp技术,以及codegen的地址等

    <build>
        <plugins>
            <!-- adding fmpp code gen -->
            <plugin>
                <artifactId>maven-resources-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-fmpp-resources</id>
                        <phase>initialize</phase>
                        <goals>
                            <goal>copy-resources</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${project.build.directory}/codegen</outputDirectory>
                            <resources>
                                <resource>
                                    <directory>src/main/codegen</directory>
                                    <filtering>false</filtering>
                                </resource>
                            </resources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <!-- 从calcite-core.jar提取解析器语法模板,并放入在${project.build}freemarker模板所在的目录 -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.8</version>
                <executions>
                    <execution>
                        <id>unpack-parser-template</id>
                        <phase>initialize</phase>
                        <goals>
                            <goal>unpack</goal>
                        </goals>
                        <configuration>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>org.apache.calcite</groupId>
                                    <artifactId>calcite-core</artifactId>
                                    <version>1.18.0</version>
                                    <type>jar</type>
                                    <overWrite>true</overWrite>
                                    <outputDirectory>${project.build.directory}/</outputDirectory>
                                    <includes>**/Parser.jj</includes>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <configuration>
                    <cfgFile>${project.build.directory}/codegen/config.fmpp</cfgFile>
                    <outputDirectory>target/generated-sources</outputDirectory>
                    <templateDirectory>${project.build.directory}/codegen/templates</templateDirectory>
                </configuration>
                <groupId>com.googlecode.fmpp-maven-plugin</groupId>
                <artifactId>fmpp-maven-plugin</artifactId>
                <version>1.0</version>
                <dependencies>
                    <dependency>
                        <groupId>org.freemarker</groupId>
                        <artifactId>freemarker</artifactId>
                        <version>2.3.28</version>
                    </dependency>
                </dependencies>
                <executions>
                    <execution>
                        <id>generate-fmpp-sources</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>

            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>javacc-maven-plugin</artifactId>
                <version>2.4</version>
                <executions>
                    <execution>
                        <phase>generate-sources</phase>
                        <id>javacc</id>
                        <goals>
                            <goal>javacc</goal>
                        </goals>
                        <configuration>
                            <sourceDirectory>${project.build.directory}/generated-sources/</sourceDirectory>
                            <includes>
                                <include>**/Parser.jj</include>
                            </includes>
                            <lookAhead>2</lookAhead>
                            <isStatic>false</isStatic>
                            <outputDirectory>${project.build.directory}/generated-sources/</outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

这里引入一张图 说明calcite中jacc和fmpp在其中起的作用
在这里插入图片描述
看到codegen中的fmpp了么 就是这个fmpp

3 flink使用calcite 生成解析器FlinkSqlParserImpl

以下面这个案例出发(代码基于 flink 1.13.1 版本):

public class ParserTest {

    public static void main(String[] args) throws Exception {

        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        env.setParallelism(10);

        EnvironmentSettings settings = EnvironmentSettings
                .newInstance()
                .useBlinkPlanner()
                .inStreamingMode()
                .build();

        StreamTableEnvironment tEnv = StreamTableEnvironment.create(env, settings);

        DataStream<Tuple3<String, Long, Long>> tuple3DataStream =
                env.fromCollection(Arrays.asList(
                        Tuple3.of("2", 1L, 1627254000000L),
                        Tuple3.of("2", 1L, 1627218000000L + 5000L),
                        Tuple3.of("2", 101L, 1627218000000L + 6000L),
                        Tuple3.of("2", 201L, 1627218000000L + 7000L),
                        Tuple3.of("2", 301L, 1627218000000L + 7000L),
                        Tuple3.of("2", 301L, 1627218000000L + 7000L),
                        Tuple3.of("2", 301L, 1627218000000L + 7000L),
                        Tuple3.of("2", 301L, 1627218000000L + 7000L),
                        Tuple3.of("2", 301L, 1627218000000L + 7000L),
                        Tuple3.of("2", 301L, 1627218000000L + 86400000 + 7000L)))
                        .assignTimestampsAndWatermarks(
                                new BoundedOutOfOrdernessTimestampExtractor<Tuple3<String, Long, Long>>(Time.seconds(0L)) {
                                    @Override
                                    public long extractTimestamp(Tuple3<String, Long, Long> element) {
                                        return element.f2;
                                    }
                                });

        tEnv.registerFunction("mod", new Mod_UDF());

        tEnv.registerFunction("status_mapper", new StatusMapper_UDF());

        tEnv.createTemporaryView("source_db.source_table", tuple3DataStream,
                "status, id, timestamp, rowtime.rowtime");

        String sql = "SELECT\n"
                + "  count(1),\n"
                + "  cast(tumble_start(rowtime, INTERVAL '1' DAY) as string)\n"
                + "FROM\n"
                + "  source_db.source_table\n"
                + "GROUP BY\n"
                + "  tumble(rowtime, INTERVAL '1' DAY)";

        Table result = tEnv.sqlQuery(sql);

        tEnv.toAppendStream(result, Row.class).print();

        env.execute();

    }

}


debug 过程如之前分析 sql -> SqlNode 过程所示,如下图直接定位到 SqlParser:

在这里插入图片描述

如上图可以看到具体的 Parser 就是 FlinkSqlParserImpl。

定位到具体的代码如下图所示(flink-table-palnner-blink-2.11-1.13.1.jar)。

在这里插入图片描述
最终 parse 的结果 SqlNode 如下图。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
再来看看 FlinkSqlParserImpl 是怎么使用 calcite 生成的。
具体到 flink 中的实现,位于源码中的 flink-table.flink-sql-parser 模块(源码基于 flink 1.13.1)。
flink 是依赖 maven 插件实现的上面的整体流程。

3.1 FlinkSqlParserImpl 的生成

在这里插入图片描述
接下来看看整个 Parser 生成流程。

3.1.1 flink 引入 calcite

使用 maven-dependency-plugin 将 calcite 解压到 flink 项目 build 目录下。

<plugin>
    <!-- Extract parser grammar template from calcite-core.jar and put
         it under ${project.build.directory} where all freemarker templates are. -->
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>unpack-parser-template</id>
            <phase>initialize</phase>
            <goals>
                <goal>unpack</goal>
            </goals>
            <configuration>
                <artifactItems>
                    <artifactItem>
                        <groupId>org.apache.calcite</groupId>
                        <artifactId>calcite-core</artifactId>
                        <type>jar</type>
                        <overWrite>true</overWrite>
                        <outputDirectory>${project.build.directory}/</outputDirectory>
                        <includes>**/Parser.jj</includes>
                    </artifactItem>
                </artifactItems>
            </configuration>
        </execution>
    </executions>
</plugin>


在这里插入图片描述

3.1.2 fmpp 生成 Parser.jj

使用 maven-resources-plugin 将 Parser.jj 代码生成。

<plugin>
    <artifactId>maven-resources-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-fmpp-resources</id>
            <phase>initialize</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>
                <outputDirectory>${project.build.directory}/codegen</outputDirectory>
                <resources>
                    <resource>
                        <directory>src/main/codegen</directory>
                        <filtering>false</filtering>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>com.googlecode.fmpp-maven-plugin</groupId>
    <artifactId>fmpp-maven-plugin</artifactId>
    <version>1.0</version>
    <dependencies>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.28</version>
        </dependency>
    </dependencies>
    <executions>
        <execution>
            <id>generate-fmpp-sources</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <cfgFile>${project.build.directory}/codegen/config.fmpp</cfgFile>
                <outputDirectory>target/generated-sources</outputDirectory>
                <templateDirectory>${project.build.directory}/codegen/templates</templateDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>


在这里插入图片描述

3.1.3 javacc 生成 parser

使用 javacc 将根据 Parser.jj 文件生成 Parser。

<plugin>
    <!-- This must be run AFTER the fmpp-maven-plugin -->
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>javacc-maven-plugin</artifactId>
    <version>2.4</version>
    <executions>
        <execution>
            <phase>generate-sources</phase>
            <id>javacc</id>
            <goals>
                <goal>javacc</goal>
            </goals>
            <configuration>
                <sourceDirectory>${project.build.directory}/generated-sources/</sourceDirectory>
                <includes>
                    <include>**/Parser.jj</include>
                </includes>
                <!-- This must be kept synced with Apache Calcite. -->
                <lookAhead>1</lookAhead>
                <isStatic>false</isStatic>
                <outputDirectory>${project.build.directory}/generated-sources/</outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>


在这里插入图片描述

3.1.4 看看 Parser

最终生成的 Parser 就是 FlinkSqlParserImpl。

在这里插入图片描述

3.1.5 blink planner 引入 flink-sql-parser

blink planner(flink-table-planner-blink) 在打包时将 flink-sql-parser、flink-sql-parser-hive 打包进去。

在这里插入图片描述

4 calcite 规则优化器

4.1 什么是查询优化器

查询优化器是传统数据库的核心模块,也是大数据计算引擎的核心模块,开源大数据引擎如 Impala、Presto、Drill、HAWQ、 Spark、Hive 等都有自己的查询优化器。Calcite 就是从 Hive 的优化器演化而来的。

优化器的作用:将解析器生成的关系代数表达式转换成执行计划,供执行引擎执行,在这个过程中,会应用一些规则优化,以帮助生成更高效的执行计划。

4.2 基于规则优化(RBO)

基于规则的优化器(Rule-Based Optimizer,RBO):根据优化规则对关系表达式进行转换,这里的转换是说一个关系表达式经过优化规则后会变成另外一个关系表达式,同时原有表达式会被裁剪掉,经过一系列转换后生成最终的执行计划。

RBO 中包含了一套有着严格顺序的优化规则,同样一条 SQL,无论读取的表中数据是怎么样的,最后生成的执行计划都是一样的。同时,在 RBO 中 SQL 写法的不同很有可能影响最终的执行计划,从而影响执行计划的性能。

4.3 基于成本优化(CBO)

基于代价的优化器(Cost-Based Optimizer,CBO):根据优化规则对关系表达式进行转换,这里的转换是说一个关系表达式经过优化规则后会生成另外一个关系表达式,同时原有表达式也会保留,经过一系列转换后会生成多个执行计划,然后 CBO 会根据统计信息和代价模型 (Cost Model) 计算每个执行计划的 Cost,从中挑选 Cost 最小的执行计划。

由上可知,CBO 中有两个依赖:统计信息和代价模型。统计信息的准确与否、代价模型的合理与否都会影响 CBO 选择最优计划。 从上述描述可知,CBO 是优于 RBO 的,原因是 RBO 是一种只认规则,对数据不敏感的呆板的优化器,而在实际过程中,数据往往是有变化的,通过 RBO 生成的执行计划很有可能不是最优的。事实上目前各大数据库和大数据计算引擎都倾向于使用 CBO,但是对于流式计算引擎来说,使用 CBO 还是有很大难度的,因为并不能提前预知数据量等信息,这会极大地影响优化效果,CBO 主要还是应用在离线的场景。

4.4 优化规则

无论是 RBO,还是 CBO 都包含了一系列优化规则,这些优化规则可以对关系表达式进行等价转换,常见的优化规则包含:

  • 谓词下推 Predicate Pushdown
  • 常量折叠 Constant Folding
  • 列裁剪 Column Pruning
  • 其他
    在 Calcite 的代码里,有一个测试类(org.apache.calcite.test.RelOptRulesTest)汇集了对目前内置所有 Rules 的测试 case,这个测试类可以方便我们了解各个 Rule 的作用。在这里有下面一条 SQL,通过这条语句来说明一下上面介绍的这三种规则。
select 10 + 30, users.name, users.age
from users join jobs on users.id= user.id
where users.age > 30 and jobs.id>10

4.4.1 谓词下推(Predicate Pushdown)

关于谓词下推,它主要还是从关系型数据库借鉴而来,关系型数据中将谓词下推到外部数据库用以减少数据传输;属于逻辑优化,优化器将谓词过滤下推到数据源,使物理执行跳过无关数据。最常见的例子就是 join 与 filter 操作一起出现时,提前执行 filter 操作以减少处理的数据量,将 filter 操作下推,以上面例子为例,示意图如下(对应 Calcite 中的 FilterJoinRule.FilterIntoJoinRule.FILTER_ON_JOIN Rule):
在这里插入图片描述
在进行 join 前进行相应的过滤操作,可以极大地减少参加 join 的数据量。

4.4.2 常量折叠(Constant Folding)

常量折叠也是常见的优化策略,这个比较简单、也很好理解,可以看下 编译器优化 – 常量折叠 这篇文章,基本不用动脑筋就能理解,对于我们这里的示例,有一个常量表达式 10 + 30,如果不进行常量折叠,那么每行数据都需要进行计算,进行常量折叠后的结果如下图所示( 对应 Calcite 中的 ReduceExpressionsRule.PROJECT_INSTANCE Rule):

在这里插入图片描述

4.4.3 列裁剪(Column Pruning)

列裁剪也是一个经典的优化规则,在本示例中对于jobs 表来说,并不需要扫描它的所有列值,而只需要列值 id,所以在扫描 jobs 之后需要将其他列进行裁剪,只留下列 id。这个优化带来的好处很明显,大幅度减少了网络 IO、内存数据量的消耗。裁剪前后的示意图如下(不过并没有找到 Calcite 对应的 Rule):

在这里插入图片描述

如果想自定义rule
可以百度 calcite 自定义rule 来实现对flinksql的 语法优化

扩展资料

Apache Calcite的优化器规则解析
Flink Sql 之 Calcite Volcano优化器(源码解析)
calcite
calcite 规则优化开发

所有代码都在我的git上,需要的同学可以自取,如果找不到可以私信我

一文速通calcite结合flink理解SQL从文本变成执行计划详细过程 阅读详情

相关推荐

空0012

12。

Direction_Wind的博客 5356

【Flink SQL引擎】:Calcite 功能简析及在 Flink 的应用

文章目录 1. Calcite 是什么? 2. Calcite 谁在用? 3. 概念解析 4. 整体模块和处理流程 5. 流处理语句支持现状 6. Flink 与 Calcite 1. Calcite 是什么? Apache Calcite 是一个动态数据的管理框架,可以用来构建数据库系统的语法解析模块 不包含数据存储、数据处理等功能 可以通过编写 Adaptor 来扩展功能,以支持不同的数据处理平台 Flink SQL 使用并对其扩展以支持 SQL 语句的

yscoder的博客 1547

Flink SQL 解析器与 Calcite 在大数据处理中的应用

Flink 使用 Calcite 作为其 SQL 解析和优化的核心组件,通过 Calcite 可以将 SQL 查询语句转换为逻辑执行计划,并进行一系列的优化操作,如谓词下推、投影消除、连接重排序等。在大数据处理领域中,Flink SQL 解析器与 Calcite 是两个重要的组件,它们在解析和优化 Flink SQL 查询方面发挥着关键作用。通过 Flink SQL 解析器,我们可以将 SQL 查询语句转换为 Flink 内部的逻Flink SQL 解析器与 Calcite 在大数据处理中的应用。

JieLun_C的博客 323

从Flink看看Calcite的使用方式

文章目录前言分析parseplanner 前言 已经有过一些博客介绍了Calcite的源码,但还没有介绍过如何使用Calcite的。Flink解析和优化用的都是Calcite,加上Flink的代码质量,应该是最适合参考的项目之一了。 分析 Flink一直致力于流批一体的处理,重构了不少代码,但是SQL的解析优化都在table模块中 1.14.3的flink依赖的calcite版本是1.26.0 parse Flink有很多自己的语法,所以在flink-sql-parse中自定义了很多语法。Flink沿用了

JiajunBernoulli的博客 2021

Apache Calcite 在 Flink 中的应用

Apache Calcite 什么是calcite Apache Calcite 是一个动态数据的管理框架,可以用来构建数据库系统的语法解析模块,是高性能数据库的基础 Standard SQL:行业标准的SQL解析器、验证器和JDBC驱动程序 Query optimization: 用关系代数【relational algebra】表示查询,使用规划规则【planning rules】进行转换,并根据成本模型进行优化 Any data, anywhere:连接到第三方数据源,浏览元数据,并通过下推进行数据

penriver的博客 1300

【Calcite】Calcite入门、架构简介

Apache Calcite是面向Hadoop新的查询引擎,它提供了标准的SQL语言、多种查询优化和连接各种数据源的能力,除此之外,Calcite还提供了OLAP和流处理的查询引擎。正是有了这些诸多特性,Calcite项目在Hadoop中越来越引入注目,并被众多项目集成。Calcite源码相关名词释义。

九师兄 790

从Calcite到Flink SQL:解析器的构建奥秘

Flink SQL借助Apache Calcite框架实现强大的SQL处理能力。Calcite作为动态数据管理框架,专注于SQL解析与优化,而将数据存储等功能交由第三方实现。其解析流程包括SQL词法语法校验和AST生成,通过JavaCC工具构建解析器。Flink SQL解析器初始化始于StreamTableEnvironmentImpl,通过PlannerFactoryUtil创建流式或批处理解析器,最终由CalciteParser完成SQL语句解析。这一设计使Flink SQL能高效处理流批数据,同时保持

qq_42773076的博客 1059

激情不灭,追寻山海:Apache Calcite PMC 之旅 Flink

Calcite PMC 和 Flink 社区合作,旨在将 Calcite 的优化能力与 Flink 的数据处理能力相结合,为用户提供更好的查询性能和灵活性。他们通过将 Calcite 的查询优化和连接能力与 Flink 的数据处理框架相结合,为用户提供了更灵活、高效的数据处理方案。在这篇文章中,我们将探索 Calcite PMC 在整合 Flink 上的努力和成就。希望本文能够帮助读者更好地了解 Apache Calcite PMC 和 Flink 的整合过程,并激发更多人对于数据处理和查询优化的兴趣。

VqhhMobile的博客 120

Flink SQL 之 Calcite Volcano优化器(源码解析)

Calcite作为大数据领域最常用的SQL解析引擎,支持Flink , hive, kylin , druid等大型项目的sql解析同时想要深入研究Flink sql源码的话calcit...

http://www.54tianzhisheng.cn/ 935

Calcite在Java中的SQL解析与执行实战指南

在现代数据处理领域,数据集成和查询优化至关重要,而Calcite框架提供了一个强大的解决方案。作为开源数据处理框架,Calcite的核心优势在于其灵活的查询解析和优化能力。本章旨在介绍Calcite框架,特别是其Query Parse模块的核心功能与工作原理。Calcite是一个用于构建数据处理系统的通用查询解析器。它支持SQL和多种数据模型,允许开发者创建定制化的查询解析器和优化器,进而与多种数据源集成。Calcite广泛应用于大数据处理、数据分析和查询优化等场景中。

weixin_42613018的博客 1302

Flink-CEPplus:基于flink 1.8源码二次开发,详见MD

Flink1.8.1-CEPplus 基于Flink1.8.1源码为CEP模块添加逻辑动态注入功能 功能描述: 使用CEP作为复杂事件处理引擎时,当逻辑频繁发生修改,以及阈值频繁调整时 整个程序需要停止后,修改代码,重新打包程序然后给集群提交,无法实现逻辑 动态修改和外部动态注入,目前已经实现了CEP逻辑动态注入,基于消息驱动逻 辑修改,可以手动往source端注入特定消息实现细腻度控制逻辑注入感知 为客户端端API中PatternStream添加方法registerListener(CepListener cepListener)注意必须在选择方法之前调用 cepListener对象需要实现接口 接口方法 Boolean needChange() 每条数据会调用这个方法,用于确定这条数据是否会触发规则更

【Calcite】Apache Calcite 框架初探及概念详解

1. 简介 Calcite 是什么?如果用一句话形容 Calcite,Calcite 是一个用于优化异构数据源的查询处理的基础框架。 最近十几年来,出现了很多专门的数据处理引擎。例如列式存储 (HBase)、流处理引擎 (Flink)、文档搜索引擎 (Elasticsearch) 等等。这些引擎在各自针对的领域都有独特的优势,在现有复杂的业务场景下,我们很难只采用当中的某一个而舍弃其他的数据引擎。当引擎发展到一定成熟阶段,为了减少用户的学习成本,大多引擎都会考虑引入 SQL 支持,但如何避免重复造轮子又成了

yiyezhiqiu167的博客 9158

Xilinx ERNIC RoCEv2 FPGA实现与QP队列深度解析

本文深入解析Xilinx ERNIC RoCEv2在FPGA上的实现,重点剖析QP队列对的管理机制与深度优化策略。通过Verilog代码示例和工程实战,详细介绍了如何实现高吞吐量、低延迟的RDMA硬件卸载方案,为金融交易和数据中心应用提供性能优化指导。

solidity8miner的博客 877

深入理解flinksql执行流程,calcite与catalog相关概念,扩展解析器实现语法的扩展

flink在执行sql语句时,是无法像java/scala代码一样直接去使用的,需要解析成电脑可以执行的语言,对sql语句进行解析转化。 这里说的我感觉其实不是特别准确,应该是 flink使用的是一款开源SQL解析工具Apache Calcite ,Calcite使用Java CC对sql语句进行了解析。 那么我们先来简单说下Calcite工具,梳理一下Calcite的基本概念: 上述图片中具体的概念解释为:Sql 的执行过程一般可以分为下图中的四个阶段,Calcite 同样也是这样 解析 校验 优化

Direction_Wind的博客 2025

告别臃肿!保姆级教程:用NTLite深度精简Win10,打造你的专属纯净系统(附完整组件移除清单)

本文提供了一份详细的NTLite教程,帮助用户深度精简Windows10系统,移除冗余组件并优化性能。从准备工作到组件移除清单,再到系统配置优化和无人值守安装,逐步指导用户打造专属纯净系统。附完整组件移除清单和实战经验,确保系统稳定高效运行。

weixin_30945039的博客 857

2021-3-20组会 无监督训练下的音频分离 (音源分离) Unsupervised Audio Source Separation Using Generative Priors

0. 说明 一片具体论文的综述

ruclion的专栏 1349

Apache Calcite 详细介绍

Apache Calcite 是一个动态数据管理框架,它提供了一套完整的 SQL 解析、验证、优化和执行引擎。与其他传统数据库不同,Calcite 不负责数据存储或具体的数据处理算法,而是专注于为各种异构数据源提供统一的 SQL 查询能力。它可以轻松集成到不同的系统中,如 Flink、Hive、Storm 等,支持开发者构建自定义的数据查询管道。Calcite:最轻量级,适合嵌入系统,但需配合外部执行器。Presto:独立运行,适合大规模 OLAP 查询。ANTLR:通用性强,但不具备优化能力。

2528

电商数据分析19——数据分析在电商平台价格弹性研究中的应用

价格弹性是一个衡量产品价格变化对销量影响的经济学指标,对于电商平台而言,深入理解和有效运用价格弹性,对于制定竞争策略、优化产品定价具有重要意义。随着大数据时代的到来,通过数据分析研究产品的价格弹性,成为了电商企业制定价格策略、调整市场定位、优化促销活动的重要依据。

theskylife的博客 2835

大数据计算引擎中的Calcite

Calcite是一个动态数据库管理框架,具备数据库管理系统的功能Calcite具备SQL解析、校验、优化、生成、连接查询等功能Calcite能够为不同平台和数据源提供统一的查询引擎。

xiaoliuxxs 2964

生信物种注释软件Kraken2+Bracken的安装与使用

一、软件安装与数据库下载 1.Kraken2安装 Kraken2是一个基于k-mer算法的高精度宏基因组序列分类软件,能够快速的将测序reads进行物种分类。 使用conda一键安装,要先安装好anaconda或者miniconda conda install -y kraken2 输入krakek2 --help 出现如下所示帮助文档,则表示安装成功。 2.Bracken安装 bracken是一种从宏基因组数据中高度准确的计算物种丰度的统计方法。 同样使用conda一键安装 conda install -

jileiqwd的博客 1万+

单细胞数据分析实战:用scDblFinder快速搞定异质性双细胞检测(附完整R代码)

本文详细介绍了如何使用scDblFinder工具在单细胞RNA测序数据中精准识别异质性双细胞。通过完整的R代码示例,从环境准备、数据加载到核心分析流程和结果可视化,帮助研究人员高效解决双细胞检测问题,提升单细胞数据分析的准确性。scDblFinder的集成算法和鲁棒性设计使其成为处理单细胞数据中技术噪音的理想选择。

weixin_29098117的博客 424

如何实现一个SQL解析器

本篇文章主要介绍如何实现一个SQL解析器来应用的业务当中,同时结合具体的案例来介绍SQL解析器的实践过程。

vivo互联网技术 2929

Jenkins+docker 微服务实现自动化部署安装和部署过程

本文详细介绍了如何使用Docker部署Jenkins自动化服务器。主要内容包括:1)拉取Jenkins官方或BlueOcean镜像;2)创建容器并配置端口映射、数据卷挂载;3)设置防火墙规则;4)配置清华大学镜像加速;5)安装必要插件;6)SSH密钥配置;7)构建触发器设置;8)编写自动化构建脚本。通过Docker部署Jenkins可以简化安装流程,确保环境一致性,并利用容器特性实现快速启动和管理。文章提供了完整的配置步骤和注意事项,帮助用户快速搭建CI/CD环境。

qq_33665793的博客 1687

Flink内核源码(七)Flink SQL提交流程

Flink内核源码:FlinkSQL提交流程分析

小朱小朱绝不认输的博客 2663

WPF基础系列六:MVVM框架

MVVM框架 文章目录MVVM框架前言一、MVVM框架简介1. 什么是MVVM?2. MVVM的优势3.MVVM的应用场景二、MVVM使用及示例 前言 在WPF开发中,经典的编程模式是MVVM,是为WPF量身定做的模式,该模式充分利用了WPF的数据绑定机制,最大限度地降低了Xmal文件和CS文件的耦合度,也就是UI显示和逻辑代码的耦合度,如需要更换界面时,逻辑代码修改很少,甚至不用修改。 与WinForm开发相比,我们一般在后置代码中会使用控件的名字来操作控件的属性来更新UI,而在WPF中通常是通过

iceberg7012的博客 2万+

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

上一篇: flink二开,实现了batch lookup join(附源码)
下一篇: flink watermark 生成机制与总结
Direction_Wind
博客等级 码龄8年 6438粉丝 102原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Direction_Wind

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值