今天在开发中遇到了一个问题,dolphinscheduler-data-quality-dev-SNAPSHOT.jar中spark sql查询clickhouse的时候对时间格式为2022-09-30 00:00:00类型的查询会自动转成2022-09-30 00:00:00.0然后再去clickhouse中查询,导致报错
- Caused by: java.lang.Throwable: Code: 53. DB::Exception: Cannot convert string 2022-09-30 00:00:00.0 to type DateTime: while executing 'FUNCTION equals(YWDATE : 6, '2022-09-30 00:00:00.0' : 11) -> equals(YWDATE, '2022-09-30 00:00:00.0') UInt8 : 17'. (TYPE_MISMATCH) (version 22.3.8.39 (official build))
-
- at ru.yandex.clickhouse.except.ClickHouseExceptionSpecifier.specify(ClickHouseExceptionSpecifier.java:53)
- ... 26 more
原因为:Dataset
通过查看clickhouse的query log可以看到
- SELECT
- *
- from
- `system`.query_log ql
- where
- query like '%ADS_FCM_ZW_KMDXFL_COMMON_DH%'
- order by
- event_time desc
在spark程序实际开发过程中遇到需要对文件内容做join操作,使用createOrReplaceTempView 方式将读取的文件创建临时表,然后通过 spark.sql()方式利用sql语句做join操作,但是数据量稍微大点时候,就会导致join效率很慢。查询资料得知,这里有优化的空间,利用 cache() 或者 persist() 方法。
createOrReplaceTempView是 transformation 算子,而transformation是lazy模式的,也就是spark不会立即计算结果,而只是简单地记住所有对数据集的转换操作逻辑,需要有action算子来触发spark应用程序,最简单的action算子:show()。例如:spark.sql("select *** from XXX ").createOrReplaceTempView(“tmp_test_table”).show()。
这样每次执行.show()算子时候,都需要先执行createOrReplaceTempView操作,导致效率很慢。肯有直接将读取出来的数据缓存起来,或者将createOrReplaceTempView之后的数据缓存到内存中。
缓存的方式有两种,具体使用不在此做赘述
1) cache()方法表示:使用非序列化的方式将RDD的数据全部尝试持久化到内存中,cache()只是一个transformtion,是lazy的,必须通过一个action触发,才能真正的将该RDD cache到内存中。
2)persist()方法表示:手动选择持久化级别,并使用指定的方式进行持久化。
如果增加cacha,会增加查询到内存的数据量,除非一开始就增加过滤条件去查询加载到内存的数据,dolphinscheduler先是全部load数据,然后注册成临时表,再在转换中去处理,在执行的时候,spark会默认将时间类型的查询条件变成yyyy-MM-dd HH:mm:ss.SSS去查询,如果数据类型为DateTime类型yyyy-MM-dd HH:mm:ss就会报错,只有类型是DateTime64类型才行!mysql因为时间类型就只有datetime所以没问题。