FlinkSQL系列02-Table表对象和SQL表视图

表概念

表标识

表标识由3部分组成:

  • catalog name (常用于标识不同的“源”, 比如 hive catalog, inner catalog 等)
  • database name(通常语义中的“库”)
  • table name(通常语义中的“表”)
// 指定使用地表标识
TableEnvironment tEnv = ...;
tEnv.useCatalog("a_catalog");
tEnv.useDatabase("db1");
// 将 table 注册到指定标识中
Table table = ...;// 注册在默认 catalog 的默认 database 中
tableEnv.createTemporaryView("a_view", table);// 注册在默认 catalog 的指定 database 中
tableEnv.createTemporaryView("db2.a_view", table);// 注册在指定 catalog 的指定 database 中
tableEnv.createTemporaryView("x_catalog.db3.a_view", table);

表和视图

Flinksql 中的表,可以是 virtual 的(view 视图)和 regular 的(table 常规表)

  • table 描述了一个物理上的外部数据源, 如文件、数据库表、kafka 消息 topic
  • view 则基于表创建, 代表一个或多个表上的一段计算逻辑(就是对一段查询计划的逻辑封装)

不管是 table 还是 view, 在 tableAPI 中得到的都是 Table 对象

临时表和永久表

  • 临时表(视图)
    创建时带 temporary 关键字(crate temporary view,createtemporary table);
    schema 只维护在所属 flink session 运行时内存中;
    当所属的 flink session 结束后表信息将不复存在; 且该表无法在 flink session 间共享;
  • 永久表(视图)
    创建时不带 temporary 关键字 (create view , create table);
    schema 可记录在外部持久化的元数据管理器中(比如 hive 的 metastore) ;
    当所属 flink session 结束后, 该表信息不会丢失; 且在不同 flink session 中都可访问到该表的信息;

区别:schema 信息是否被持久化存储

表定义

创建 table 表对象

Table 对象获取方式解析:

  • 从已注册的表

    Table t1 = tenv.from("t1"); // 通过已经在 env 的 catalog 中注册的表名, 获得 Table 对象
    
  • 从 TableDescriptor(连接器/format/schema/options)

    Table table = tenv.from(TableDescriptor
                .forConnector("kafka")  // 指定连接器
                .schema(Schema.newBuilder()  // 指定表结构
                        .column("id", DataTypes.INT())
                        .column("name", DataTypes.STRING())
                        .column("age", DataTypes.INT())
                        .column("gender", DataTypes.STRING())
                        .build())
                .format("json")  // 指定数据源的数据格式
                .option("topic", "doit30-3")  // 连接器及format格式的相关参数
                .option("properties.bootstrap.servers", "doit01:9092")
                .option("properties.group.id", "g2")
                .option("scan.startup.mode", "earliest-offset")
                .option("json.fail-on-missing-field", "false")
                .option("json.ignore-parse-errors", "true")
                .build());
    
  • 从 DataStream

    // 1 不指定schema,将流创建成Table对象,表的schema是默认的,往往不符合我们的要求
    Table table1 = tenv.fromDataStream(kfkStream);
    /*table1.execute().print();*/
    
    // 2 为了获得更理想的表结构,可以先把数据流中的数据转成javabean类型
    SingleOutputStreamOperator<Person> javaBeanStream = kfkStream.map(json -> JSON.parseObject(json, Person.class));
    Table table2 = tenv.fromDataStream(javaBeanStream);
    /*table2.execute().print();*/
    
    // 3 手动指定 schema定义,来将一个javabean流,转成Table对象
    Table table3 = tenv.fromDataStream(javaBeanStream,
           Schema.newBuilder()
                   .column("id",DataTypes.BIGINT())
                   .column("name",DataTypes.STRING())
                   .column("age",DataTypes.INT())
                   .column("gender",DataTypes.STRING())
                   .build());
    
  • 从 Table 对象上的查询 api 生成

    Table table = table3.select($("guid"), $("uuid"));
    
  • 从测试数据

    Table table = tenv.fromValues(
                DataTypes.ROW(
                        DataTypes.FIELD("id",DataTypes.INT()),
                        DataTypes.FIELD("name",DataTypes.STRING()),
                        DataTypes.FIELD("age",DataTypes.DOUBLE())
                ),
                Row.of(1, "zs", 18.2),
                Row.of(2, "bb", 28.2),
                Row.of(3, "cc", 16.2),
                Row.of(4, "dd", 38.2)
        );
    

创建 sql 表视图

  • 从已存在的 datastream 注册

    tenv.createTemporaryView("t_person", javaBeanStream);
    tenv.executeSql("select gender,max(age) as max_age from t_person group by gender").print();
    
  • 从已存在的 Table 对象注册

    tenv.createTemporaryView("t1",table);
    
  • 从 TableDescriptor(连接器) 注册

    tenv.createTable("table_a",  // 表名
            TableDescriptor.forConnector("filesystem")
                    .schema(Schema.newBuilder()
                            .column("id", DataTypes.INT())
                            .column("name", DataTypes.STRING())
                            .column("age", DataTypes.INT())
                            .column("gender", DataTypes.STRING())
                            .build())
                    .format("csv")
                    .option("path", "data/sqldemo/a.txt")
                    .option("csv.ignore-parse-errors", "true")
                    .build());
    
    
    tenv.executeSql("select * from table_a").print();
    
  • 执行 Sql 的 DDL 语句来注册

    tenv.executeSql(
    "CREATE TABLE age_info "
    + "( "
    + " id INT, "
    + " name string, "
    + " gender string, "
    + " age int, "
    + " PRIMARY KEY (id) NOT ENFORCED "
    + ") WITH ( "
    + " 'connector' = 'mysql-cdc', "
    + " 'hostname' = 'hdp01', "
    + " 'port' = '3306', "
    + " 'username' = 'root', "
    + " 'password' = '123456', "
    + " 'database-name' = 'abc', "
    + " 'table-name' = 'age_info' "
    + " ) ");
    tenv.executeSql("select * from age_info").print();
    

catalog

什么是 catalog

catalog 就是一个元数据空间,简单说就是记录、获取元数据(表定义信息)的实体;

flinksql 在运行时,可以拥有多个 catalog,它们由 catalogManager 模块来注册、管理;

  1. 环境创建之初,就会初始化一个默认的元数据空间

    • 空间名称: default_catalog
    • 空间实现类: GenericInMemoryCatalog
  2. 用户还可以向环境中注册更多的 catalog,如下代码新增注册了一个 hivecatalog

    // 创建了一个 hive 元数据空间的实现对象
    HiveCatalog hiveCatalog = new HiveCatalog("hive", "default", "/hiveconf/dir");
    // 将 hive 元数据空间对象注册到 环境中
    tenv.registerCatalog("mycatalog",hiveCatalog);
    

如何理解 hive catalog

  • flinksql 利用 hive catalog 来建表(查询、修改、删除表),本质上只是利用了 hive 的 metastore 服务;
  • 更具体来说,flinksql 只是把 flinksql 的表定义信息,按照 hive 元数据的形式,托管到 hive 的 metastore 中而已;
  • 当然,hive 中也能看到这些托管的表信息,但是,并不能利用它底层 mapreduce 或 spark 引擎来查询这些表;因为 mapreduce 或者 spark 引擎,并不能理解 flinksql 表定义中的信息,也无法为这些定义信息提供相应的组件去读取数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值