[实战-12] flinkSql 时间属性

flinkSql 时间属性

  • [一. 摘要](#一. 摘要)
  • [二.flink 时间数据类型](#二.flink 时间数据类型)
      • [2.1. TIMESTAMP(n)](#2.1. TIMESTAMP(n))
      • [2.2. TIMESTAMP_LTZ(n)](#2.2. TIMESTAMP_LTZ(n))
  • [三.flink 受时区影响的时间函数](#三.flink 受时区影响的时间函数)
  • [五. time Attributes](#五. time Attributes)
    • [5.1. event_time](#5.1. event_time)
    • [5.2. process_time](#5.2. process_time)
  • [六. event_time 时间字段转化](#六. event_time 时间字段转化)
  • [六. process_time 时间字段转化](#六. process_time 时间字段转化)
  • 七.参考链接

一. 摘要

在阅读下面知识之前,读者需要先看 Flinksql设置时区

flink兼容很多上游数据库,一般要求数据库中的字段类型为datetime或者是timestamp的时候,flinksql create table的时候可以用TIMESTAMP()或者TIMESTAMP_ltz()接收

如果上游数据是string或者是long则需要转化,这块后面再说。

2.1. TIMESTAMP(n)

是 TIMESTAMP(n) WITHOUT TIME ZONE 的简写,不携带时区信息。意思是你再源数据库中看到的yyyy-MM-dd

hh:MM:ss是什么样子, 在flink中看到的就是什么样子。换句话说
TIMESTAMP(n)相当于一个字符串类型,无论作业时区怎么变,得到的字符串是不变的。

注意:TIMETSAMP(n) 在flink中是 字符串,字符串,字符串,重要的事情说三遍

2.2. TIMESTAMP_LTZ(n)

是TIMESTAMP§ WITH LOCAL TIME ZONE的简写, 是一个全球统一的时间点类型,

它底层不是字符串,属于Bigint类型。如果将其转为字符串,则结果会随着作业时区改变。

flinksql查看执行结果的时候,不管是TIMESTAMP()还是TIMESTAMP_LTZ我们看到的都是字符串.

TIMESTAMP_LTZ展示给我们的 字符串 会随着时区的table.local-time-zone 的设置而变化。这点要注意哦。

而TIMESTAMP(n)底层本身就是 字符串 , 是和时区没有关系的。 这就是两个的区别。

注意:TIMETSAMP(n) 在flink中是 long,long,long,重要的事情说三遍

函数 例子
LOCALTIME 15:18:36
LOCALTIMESTAMP 2021-04-15 15:18:36.384
CURRENT_DATE 2021-04-15
CURRENT_TIME 15:18:36.384
CURRENT_TIMESTAMP 2021-04-15 15:18:36.384
CURRENT_ROW_TIMESTAMP() 2021-04-15 15:18:36.384
NOW() 2021-04-15 15:18:36.384
PROCTIME() 2021-04-15 15:18:36.384
  • TIMESTAMP(n) 对flink来说是string不受到时区的影响
    不管如何设置时区,我们看到的日期字符串都是不变的
  • TIMESTAMP_LTZ(n) 对flink来说是long,受到时区影响
    对我们来说看到的都是yyyy-MM-dd hh:MM:ss格式的字符串,
    long->可见的字符串这个过程 是受到时区影响的 因此时区不同我们看到的字符串也是不同的。

五. time Attributes

我们知道,flink常见的事件事件和处理时间, 二者都可以用来开窗口计算。

event_time和process_time都是时间类型,被称为time Attributes(时间属性)

5.1. event_time

复制代码
可用必须是timestamp()或者是timestamp_ltz 的类型

5.2. process_time

复制代码
flink-1.13之前PROCTIME()  用的是TIMESTAMP(3)字符串类型,且这个字符串是UTC时区转化的字符串
flink-1.13只后PROCTIME() 用的是TIMESTAMP_LTZ() 会自动按照当前sessoin的时区转换。

对flink来说外界数据时间,需要转化为fink识别的TIMESTAMP或者TIMESTAMP_LTZ(),才可以进行flink后续的窗口计算。窗口以及水位线的声明需要依赖转化后的 时间字段

六. event_time 时间字段转化

  • DDL 指定水位线和进行时间字段的转化

    sql 复制代码
    	CREATE TABLE user_actions (
    	  time_str STRING,
    	  t1 as TO_TIMESTAMP(time_str,'yyyy-MM-dd HH:mm:ss'),
    	  t2 AS TO_TIMESTAMP_LTZ(time_long,3),
    	  time_datetime TIMESTAMP(3),
    	  //WATERMARK FOR t1 AS t1 - INTERVAL '5' SECOND,
    	 // WATERMARK FOR t2 AS t2 - INTERVAL '5' SECOND,
    	  //WATERMARK FOR time_datetime  AS time_datetime - INTERVAL '5' SECOND,
    	) WITH (
    	  ...
    	);

    主要分为几种情况

    1. 数据库中是yyyy-MM-dd hh:MM:dd 的string
      需要借助函数TO_TIMESTAMP(字符串字段,'yyyy-MM-dd hh:MM:ss)
    2. 数据库是datetime或者timestamp
      可直接被识别为TIMESTAMP(n)不需要转化
    3. 数据库中是long 时间戳
      需要借助函数需要借助函数TO_TIMESTAMP_LTZ(long字段,精度)
      ts AS TO_TIMESTAMP_LTZ(time_long,3) 意思是将time_long 按照flink中设置的时区转化为 flink可识别的TIMESTAMP_LTZ(3)
      并将转化后的值 命名为ts字段

    注意上面sql中被注释的部分,意思是转化后的时间字段,就可以被用于水位线设置了

  • fromDataStream 或fromChangeStream()的时候

    这种情况必须借助 Scheme 定义水位线和时间属性

  1. 如果DatasStream 提前定义了事件事件和水位线,则Scheme可直接提取
    DataStream Api中有个隐藏是rowtime 属性,该属性其实就是event_time, 我们可以通过以下方式直接获取
java 复制代码
           Schema.newBuilder()
               .columnByMetadata("rowtime", "TIMESTAMP_LTZ(3)") // 获取元数据中的rowtime属性,其实就是event_time
               .watermark("rowtime", "SOURCE_WATERMARK()")  // 意思是获取DataStream的水位线传播到Table Api
               .build()
  1. 如果DatasStream 没有定义事件事件和水位线,此时需要在转换的时候重新定义水位线
    假设DataStream中数据有个字段叫做my_time是个long类型的时间戳,则通过以下方式定义新的水位线
java 复制代码
        Schema s1=Schema.newBuilder()
                .columnByExpression("myrowtime", "CAST(my_time AS TIMESTAMP_LTZ(0))")
               // .columnByExpression("myrowtime", "TO_TIMESTAMP(my_time)")
              //  .columnByExpression("myrowtime", "TO_TIMESTAMP_LTZ(my_time,3)") 
                .watermark("myrowtime", "myrowtime- INTERVAL '10' SECOND")
                .build();
        string类型也可以用TO_TIMESTAMP(my_time) 转换
        long类型也可以用TO_TIMESTAMP_LTZ(my_time,3)转换
        CAST那种写法比较暴力,直接是类型转换

六. process_time 时间字段转化

比较简单,直接用 PROCTIME() 函数就行了

  • DDL

    sql 复制代码
    	CREATE TABLE user_actions (
    		  process_time AS PROCTIME() 
    		) WITH (
    		  ...
    		);
    	```
  • fromDataStream

    复制代码
      Schema schema = Schema.newBuilder()
              .columnByExpression("proctime", "PROCTIME()")
              .build();

七.参考链接


time-zone

相关推荐
笃行3502 分钟前
国产化落地避坑 · 干货向|Oracle 迁金仓 KES,我把外连接消除排在隐性陷阱第一位
数据库
老纪的技术唠嗑局21 分钟前
花一年时间整理出的:AI 数据库混合搜索入门实践
数据库
星夜夏空991 小时前
网络编程(1)
服务器·网络
川石课堂软件测试1 小时前
安全测试|常见SQL注入攻击方式、实例及预防
服务器·数据库·sql·功能测试·测试工具·安全·单元测试
上海云盾-小余1 小时前
中小站点防护避坑:低价高防服务存在的各类安全短板剖析
网络·爬虫·安全·ddos
笃行3501 小时前
国产化落地避坑 · 干货向|迁移后那条「测试能过、一上生产就查空」的 SQL,多半栽在 WHERE 函数顺序上
数据库
蓝田~2 小时前
MySQL慢查询怎么优化?B+Tree索引原理+MVCC读不阻塞写+EXPLAIN执行计划,从5秒到0.05秒
数据库·mysql
sunxunyong2 小时前
doris用户资源组配置
数据库
Cloud云卷云舒3 小时前
云卷云舒:HaishanDB的AI原生能力主要应用场景
数据库·人工智能·ai-native·haishandb·移动云长期记忆
时间的拾荒人3 小时前
MySQL 视图详解
android·数据库·mysql