文章导读:
什么是 Calcite?
Calcite 的主要功能?
如何快速使用 Calcite?
什么是 Calcite
Apache Calcite 是一个动态数据管理框架, 它具备很多典型数据库管理系统的功能, 比如 SQL 解析, SQL 校验, SQL 查询优化, SQL 生成以及数据连接查询等, 但是又省略了一些关键的功能, 比如 Calcite 并不存储相关的元数据和基本数据, 不完全包含相关处理数据的算法等.
也正是因为 Calcite 本身与数据存储和处理的逻辑无关, 所以这让它成为与多个数据存储位置 (数据源) 和多种数据处理引擎之间进行调解的绝佳选择.
Calcite 所做的工作就是将各种 SQL 语句解析成抽象语法树(AST Abstract Syntax Tree), 并根据一定的规则或成本对 AST 的算法与关系进行优化, 最后推给各个数据处理引擎进行执行.
目前, 使用 Calcite 作为 SQL 解析与优化引擎的又 Hive,Drill,Flink,Phoenix 和 Storm,Calcite 凭借其优秀的解析优化能力, 会有越来越多的数据处理引擎采用 Calcite 作为 SQL 解析工具.
Calcite 主要功能
Calcite 的主要功能我们上面其实已经提到了, 主要有以下功能:
SQL 解析: 通过 JavaCC 将 SQL 解析成未经校验的 AST 语法树
SQL 校验: 校验分两部分, 一种为无状态的校验, 即验证 SQL 语句是否符合规范; 一种为有状态的即通过与元数据结合验证 SQL 中的 Schema,Field,Function 是否存在.
SQL 查询优化: 对上个步骤的输出 (RelNode) 进行优化, 得到优化后的物理执行计划
SQL 生成: 将物理执行计划生成为在特定平台 / 引擎的可执行程序, 如生成符合 MySQL or Oracle 等不同平台规则的 SQL 查询语句等
数据连接与执行: 通过各个执行平台执行查询, 得到输出结果.
所以在 Calcite 中, 一条 SQL 的处理步骤就很清晰了, 那么我们通过 Calcite 的代码来实际了解一下:
- // 初始化配置
- SqlParser.ConfigBuilder configBuilder = SqlParser.configBuilder();
- configBuilder.setUnquotedCasing(Casing.UNCHANGED);
- //Sql 解析: 解析 Sql 语句, 通过 JavaCC 解析成 AST 语法树, 表现为 SqlNode
- SqlParser sqlParser = SqlParser.create(sql, configBuilder.build());
- SqlNode sqlNode = sqlParser.parseQuery();
- //Sql 校验: 结合元数据信息验证 Sql 是否符合规范
- Planner planner = Frameworks.getPlanner(config);
- SqlNode node = planner.validate(sqlNode);
- //Sql 查询优化: 将 SqlNode 转换为 LogicalPlan, 表现为 RelNode
- RelRoot relRoot = planner.rel(node);
- RelNode project = relRoot.project();
- // 指定优化规则
- final HepProgram program = new HepProgramBuilder()
- .addRuleInstance(SubQueryRemoveRule.PROJECT)
- .addRuleInstance(SubQueryRemoveRule.FILTER)
- .addRuleInstance(SubQueryRemoveRule.JOIN)
- .build();
- // 生成优化后的 RelNode
- HepPlanner prePlanner = new HepPlanner(program);
- prePlanner.setRoot(project);
- RelNode relNode = prePlanner.findBestExp();
- //ToDo 执行查询
使用 Calcite
那么前面对 Calcite 进行了简单的介绍, 我们如何使用 Calcite 呢? Calcite 的使用非常简单, 你要做的只是添加数据源即可. 我们以 MySQL 数据源为例, 我们通过添加 MySQL 数据库作为 Calcite 的数据源, 实现通过 Calcite 对 MySQL 数据进行查询的 Demo.
- // 初始化 calcite connection
- Class.forName("org.apache.calcite.jdbc.Driver");
- Properties info = new Properties();
- info.setProperty("lex", "JAVA");
- Connection connection =
- DriverManager.getConnection("jdbc:calcite:", info);
- CalciteConnection calciteConnection =
- connection.unwrap(CalciteConnection.class);
- // 添加 MySQL 数据库作为数据源
- SchemaPlus rootSchema = calciteConnection.getRootSchema();
- Class.forName("com.mysql.jdbc.Driver");
- BasicDataSource dataSource = new BasicDataSource();
- dataSource.setUrl("jdbc:mysql://localhost");
- dataSource.setUsername("username");
- dataSource.setPassword("password");
- Schema schema = JdbcSchema.create(rootSchema, "hr", dataSource,
- null, "name");
- rootSchema.add("hr", schema);
- // 执行查询
- Statement statement = calciteConnection.createStatement();
- ResultSet resultSet = statement.executeQuery(
- "select d.deptno, min(e.empid)\n"
- + "from hr.emps as e\n"
- + "join hr.depts as d\n"
- + "on e.deptno = d.deptno\n"
- + "group by d.deptno\n"
- + "having count(*)> 1");
- print(resultSet);
- resultSet.close();
- statement.close();
- connection.close();
Calcite 提供了多种方式添加数据源, 如通过 "inline:" 的字符串方式以及通过 JSON 或 YAML 文件的方式. 同时, Calcite 抽象出了功能齐全的接口, 可以方便的将 CSV 文件抽象成数据表进行查询. 这部分内容可以通过官方的示例了解一下!
当然 SQL 解析, 校验与执行计划优化是 Calcite 的基本功能, Calcite 的 NB 之处在于, Calcite 的目标是 "one size fits all", 希望能为不同的计算平台和数据源提供统一的查询引擎, 并且以类似传统数据库的访问方式 (SQL) 来访问 Hadoop 上的数据. 所以 Calcite 提供了非常丰富的可扩展接口, 帮助我们实现扩展数据源, 扩展针对不同数据源的优化规则, 扩展 SQL 查询语法, 扩展数据处理引擎等等. 这部分后面会详细介绍(挖坑 ing)
参考资料:
https://calcite.apache.org/docs/tutorial.html
好久不更新了
来源: http://www.bubuko.com/infodetail-2981138.html