Apacheの方解石論文の研究ノート

ビッグデータ処理技術とオープンソース製品の実現の最近の関心は、多くのプロジェクトは、Apache方解石と呼ばれるものを記載していることがわかりました。同じことは、注目を集める必要があり、再び言及したデータ処理製品の異なる期間であってもよいし、1または2を見ることは驚くべきことではありません。この理由のためにも、この上のものにいくつかの情報見つけSIGMODに掲載された2018紙、私はそれが最も適切なエントリをもたらしたと思うし、そして以下は、私が何を考えていると、この論文の要約。

何ですか

最適化されたクエリ処理のオーバー異種データソース(異種データソースに対してクエリ処理の最適化のための基本的なフレームワーク)のためのファウンフレームワーク - どのような紙のタイトルと説明方解石であることは、最も適切です。方解石は、標準のSQL言語、マルチクエリの最適化と、さまざまなデータソースを接続する機能を提供します。機能的な観点から、等SQL解析、SQLチェック、SQLクエリ最適化、SQL生成、データ接続照会、などの典型的なデータベース管理システムの機能の多くを有するが、データ処理、データ記憶および他のDBMSのコア機能を含んでいません。一方、なぜならそのような設計のデータ処理及び記憶の方解石独立の、それは複数のデータソースとデータ処理エンジン間の連携に最適となります。

方解石は、Apache Hiveのプロジェクト、ハイブベースの最適化モデルのためのコスト、すなわち、CBO(コストベースの最適化)のため、当初optiq、前optiqと呼ばれています。Apacheのコミュニティプロジェクトのインキュベーターになることを、独立した2014年5月optiqは、2014年9月に正式に方解石に社名を変更しました。このプロジェクトの目標は、1つのサイズが異なるコンピューティングプラットフォームやデータソースのための統一されたクエリ・エンジンを提供することを望んで、すべて(のシーンのすべてのニーズに適応するためのスキームを)フィットです。

方解石は、SQLの主な機能の解析(パース)と最適化(optimazation)です。まず、抽象構文ツリー(AST抽象構文木)にSQL文を解析し、特定の規則またはアルゴリズムのコストに基づいて、実行のためにそれぞれのデータ処理エンジンにAST、最終的なプッシュの間の関係を最適化します。

何故

我々はそれが図書館のようにSQLの構文解析と最適化が必要なのか、なぜ次の質問は、ありますか?

あなたは、分散コンピューティング製品から勉強する準備ができている場合は、最終的にはSQLに似た実行される機能、および、そのような機能の実現を解決する必要があり、特定の技術的なしきい値があり、設計者は、リレーショナル代数や他の分野のより深い理解を持っている必要があります。SQLの解析結果も試してみても、会社の宣伝費、ユーザーの学習コストを削減する主流のANSI-SQL契約、する必要があります。また、次のシナリオによって算出大規模な分散データ処理時間、SQLは、しばしば考慮構文木が、論理演算を複数のセマンティックツリーなどを解決することができ、異なるデータ構造、基礎となるデータの処理の順序などは、フィルタ内部で接続されています、これらの構文木間の効率の特定の実装に応じて、しばしば非常に異なる、別のSQL文、基礎となる実行環境です、オプションの長所と短所も異なる存在します。

そのため、構文木の実行パスを最適化する方法が非常に重要な課題です。この二点、バッチ・コンピューティングにおける大規模データ処理、ストリーム・コンピューティングでは、対話型のクエリや他の地域は、多かれ少なかれになり、いくつかの共通の問題があり、クエリ処理と最適化パッケージ、背後関係代数クエリー後に抽象的な問題、共通の枠組みを生成することが可能。

あなたはデータのユーザであれば、あなたは複数の異種データソースを統合する必要性に直面することができる(従来のリレーショナルデータベースは、このようなESなどの検索エンジンで、このようにMongoDB、などスパーク、などの分散コンピューティングフレームワークとしてのキャッシング製品は)、この時点でも可能ですクロスプラットフォームの分散クエリの最適化と実行の問題に直面しました。

見つけます

そうアパッチ方解石は、それが完全なクエリ処理システムとして配置されているが、方解石は、実用的なプロジェクトは、一般的に2つの方法で使用される非常に柔軟であるように設計されている論文を浮上しました。

  1. 自分のプロジェクトに、ライブラリとしてlibが方解石。

    システムリストに自社製品の方解石

  2. データソース方解石アダプタと一体化プログラムを読み出すことにより、アダプタ(アダプタ)を実装します。

    システムは、リスト方解石アダプタを使用しています

集計関数

5つの部分をDBMS

一般的に、我々は、グレーデータ管理およびデータ・ストレージは、外部コンピューティングへ開いているときに、データベース管理システムは、方解石は青色で表示のみ三つの部分を、識別された設計および実装の問題から開始して、上記のように5つの部分に分割されて置くことができます達成するためのストレージエンジン。これの目的は、データ自体の特性は、通常、データ管理、(ファイル、リレーショナルデータベース、列データベース、分散ストレージなど)多様かつ複雑であるデータ記憶部をもたらすされ、方解石は二つの部分をあきらめ、より一般的な上部に焦点を当てますモジュールは、制御下システムの複雑させ、彼らの関係者様に焦点を当て、より良い技術では、より深く行うことができます。

方解石は、ホイールを作成するために繰り返していなかった、既製、このようJavaCCのSQL文のJavaコードにオープンソースを直接使用するのこの部分を解析するなど、SQLの次の段階のための抽象構文木に変換して利用できるものを持ってきました使用しています。別の例は、柔軟なメタデータ機能を実現するために、方解石は、Javaコードが実行されてコンパイルすることをサポートする必要があり、デフォルトのjavacは、あまりにも、オープンソースJaninoの使用に、ここで、より軽量なコンパイラが必要です。

この関数は、フォーカス、ホイールを作成繰り返さない、シンプルなデザインのアイデアは、方解石は、シンプルかつ十分な安定を達成するのに十分な製品を作るために。

柔軟なプラグイン可能なアーキテクチャ

方解石のアーキテクチャ

ルール、メタデータプロバイダと計画エンジン:方解石は、オプティマイザは、その中に示される、内部最適化エンジンは、3つの主要コンポーネントから構成されるよう関係方解石演算子ツリーを使用し、図のアーキテクチャは、用紙を記載されています。点線は、それが図からわかるように、外部方解石の相互作用を表している。いくつかの方法は、この相互作用があります。

上図は、通常、SQL文、JDBCクライアントJDBCサーバーを介して内部方解石のアクセスとして入力しアクセスするために、外部JDBCクライアント・アプリケーションを表します。次のJDBCサーバーは、SQLの構文解析と検証、および方解石は、SQLの構文解析と検証用ドッキングを行うサポートするための式ビルダーに次のフレームを行うSQLパーサとバリデータモジュールを通じてSQL文を渡します。そして、外部のカスタムメタデータをサポートするために、関係式、メタデータプロバイダを処理するために、演算子式モジュールを踏襲し、プラグイン可能なルールが最適化ルールを定義するために使用される、クエリオプティマイザのコアは、クエリの最適化に焦点を当てています。

方解石内部は、クエリパーサーとバリデータを含み、それは、SQLクエリ関係演算子ツリーに変換することができます。アダプタ等ビュー定義テーブルを介して機構を提供するデータ記憶層が、こうして方解石は、外部ストレージエンジンのエンジンに格納されている上層に使用することができるので、カルサイトは含まれていません。方解石のみ最適化されたSQLデータベース言語のサポートシステムを提供することができない、また、すでに独自の言語の構文解析と解釈されているシステムのために最適化されたサポートを提供します。

あなたが統合された機能の一部のみを選択して使用することを可能にする、機能モジュールは、より多くの、独立した合理的な、方解石が完全に統合することができないので。基本的に、すべてのモジュールは、ユーザーがより柔軟なカスタマイズ機能を実現することを可能にするカスタムをサポートしています。

どのように行います

方解石は、以下の一般的なSQL構文解析の手順があります。1.分析(パーサー)、JavaのCC検証されていないSQLによって方解石はAST 2.を確認(検証)に解析、このステップは、検証段階での主要な役割がありますASTは、この手順3ツリー生成RelNode最適化(最適化)が完了した後、主な役割は、ステップRelNodeツリーを最適化することで、そのような認証SQL方式、フィールド、機能、等がある場合、SQL文のように合法として、正当です物理的な実施計画に変換します。SQLの最適化2つの一般的なルールがあります。検証した後RelNodeツリーは、実際に直接物理的な実施計画を変換することができた後、ルールベース・オプティマイザ(RBO)は、コストベースの最適化(CBO)は、原則的にはこのステップはオプションであることを言いましたしかし、近代的なSQLパーサ基本的には、このステップ、SQL実行計画を最適化するためです。このステップの結果は、物理的な実施計画を取得することです。4.(実行)を実行し、この手順は、主に行うことにある物理的な実装計画にプログラムを変換するためにある特定のプラットフォームで実行することができます。ハイブ、FLINKこの段階では、コード生成は、対応する実行可能なコードを生成する物理的な実行計画です。

ここでは、クエリデモ方解石の一例であり、我々は、SQLクエリを記述しモデル化しますが、内部のデータストレージおよび任意のDBを使用しませんでしたが、JVMによってメモリに格納されたデータ。方解石の使用によって、この例の簡単な視覚があるかもしれません。

Mavenの導入

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.study.calcite</groupId>
    <artifactId>demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!--calcite 核心-->
        <dependency>
            <groupId>org.apache.calcite</groupId>
            <artifactId>calcite-core</artifactId>
            <version>1.19.0</version>
        </dependency>

    </dependencies>
</project>
复制代码

構造のスキーマ定義

スキーマは、一例で呼び出さJavaHrSchemaのスキーマを定義し、それは内部データベースDBインスタンスに例えることができるものの構造を表すデータを格納するための構造を定義します。部門と従業員表2内のスキーマは、それらがいくつかのデータを初期化するメモリ、例えば、データベーステーブルとして、最後の2つのテーブルを理解することができます。

package org.study.calcite.demo.inmemory;

/**
 * 定义 Schema 结构
 *
 * @author niwei
 */
public class JavaHrSchema {

    public static class Employee {
        public final int emp_id;
        public final String name;
        public final int dept_no;

        public Employee(int emp_id, String name, int dept_no) {
            this.emp_id = emp_id;
            this.name = name;
            this.dept_no = dept_no;
        }
    }

    public static class Department {
        public final String name;
        public final int dept_no;

        public Department(int dept_no, String name) {
            this.dept_no = dept_no;
            this.name = name;
        }
    }

    public final Employee[] employee = {
            new Employee(100, "joe", 1),
            new Employee(200, "oliver", 2),
            new Employee(300, "twist", 1),
            new Employee(301, "king", 3),
            new Employee(305, "kelly", 1)
    };

    public final Department[] department = {
            new Department(1, "dev"),
            new Department(2, "market"),
            new Department(3, "test")
    };
}
复制代码

Javaのコード例

次のステップは、SQL文を書くことで、実行、前提はこれらの事は、データ・ソースを追加するために方解石が必要で動作させるためのスキーマ、テーブル定義方解石電流を、教えてやることです。APIは、ビューの方解石ポイントから提供していますし、実際にはJDBCデータベース・アクセス・コードに非常に似ている、学生はこのコードが導入されていない、確かに精通している書いています。

package org.study.calcite.demo.inmemory;

import org.apache.calcite.adapter.java.ReflectiveSchema;
import org.apache.calcite.jdbc.CalciteConnection;
import org.apache.calcite.schema.SchemaPlus;

import java.sql.*;
import java.util.Properties;

public class QueryDemo {
    public static void main(String[] args) throws Exception {
        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);

        SchemaPlus rootSchema = calciteConnection.getRootSchema();
        /**
         * 注册一个对象作为 schema ,通过反射读取 JavaHrSchema 对象内部结构,将其属性 employee 和 department 作为表
         */
        rootSchema.add("hr", new ReflectiveSchema(new JavaHrSchema()));
        Statement statement = calciteConnection.createStatement();
        ResultSet resultSet = statement.executeQuery(
                "select e.emp_id, e.name as emp_name, e.dept_no, d.name as dept_name "
                        + "from hr.employee as e "
                        + "left join hr.department as d on e.dept_no = d.dept_no");
        /**
         * 遍历 SQL 执行结果
         */
        while (resultSet.next()) {
            for (int i = 1; i <= resultSet.getMetaData().getColumnCount(); i++) {
                System.out.print(resultSet.getMetaData().getColumnName(i) + ":" + resultSet.getObject(i));
                System.out.print(" | ");
            }
            System.out.println();
        }

        resultSet.close();
        statement.close();
        connection.close();

    }
}
复制代码

おすすめ

転載: juejin.im/post/5d2ed6a96fb9a07eea32a6ff