阿里云大数据实战记录10:Hive 兼容模式的坑


文章目录

    • 1、前言
    • 2、什么是 Hive 兼容模式?
    • 3、为什么要开启 Hive 模式?
    • 4、有什么副作用?
    • 5、如何开启 Hive 兼容模式?
    • 6、该场景下,能不能不开启 Hive 兼容模式?
    • 7、为什么不是`DATE_FORMAT(datetime, string)`?
    • 8、小结

1、前言

今天在开发一个表单的时候,MaxCompute 抛给我一个错误:

SQL Runtime Unretryable Error: ODPS-0121125:[xx,xx] Unsupported operation - function signature DATE_FORMAT(string, string) is not supported in current mode, please set odps.sql.hive.compatible=true to use it

什么意思呢?就是告诉我 MaxCompute 不支持这个语法DATE_FORMAT(string, string),但是如果我还是想用的话可以加上一个配置:set odps.sql.hive.compatible=true,这样就可以使用以上语法。

这个报错原本的 SQL 可以抽象为:

SELECT DATE_FORMAT(FROM_UNIXTIME(1672538400),'yyyyMMdd')

也就是FROM_UNIXTIME(1672538400)返回结果被当作 STRING 数据类型处理了。而DATE_FORMAT(string, string)需要加上set odps.sql.hive.compatible=true才能正常工作。

2、什么是 Hive 兼容模式?

那么这个配置(set odps.sql.hive.compatible=true)是什么意思呢?
这个配置就是开启 Hive 兼容模式,使得在 MaxCompute SQL 中可以使用 Hive SQL 的函数语法。

3、为什么要开启 Hive 模式?

因为有一些函数的用法 MaxCompute 不支持,或者有差异,要开启 Hive 模式才能使用。
比如说上面报错:DATE_FORMAT()函数如果传入的参数是 STRING 类型,则需要开启 Hive 兼容模式才可以使用。否则就报错。

如上,MaxCompute 中,使用DATE_FORMAT()函数时,传入的参数不支持 STRING 类型,DATE_FORMAT(string,string)在 Hive SQL 才被支持,所以需要通过开启 Hive 兼容模式来使用它。

4、有什么副作用?

当然!肯定会有副作用,因为 Hive 模式和非 Hive 模式的一些函数的返回值是不同的。
比如说FROM_UNIXTIME()函数,它在 Hive 兼容模式下的返回值为 STRING 类型,而在 ODPS 1.0 和 ODPS 2.0 数据类型版本的返回值为 DATETIME 类型。

这会有什么影响呢?如果你使用过 MaxCompute 进行数据开发,一定不会陌生:MaxCompute 在数据类型一致性这方面要求会比较苛刻,绝大多数场景下数据类型不一致会无法判断

这时,要么抛出错误,要么直接返回空值,前者还容易处理,进行显性调整数据类型即可,后者就有点摸不着头脑,需要逐步排查。

所以,返回数据类型改变了,最大的影响就是取不到数据,也正因为这个原因,开发的表单一定要进行数据校验,避免翻车。

说个题外话,数据类型一致性这点在 MySQL 上几乎是看不见的,因为 MySQL 会帮我们进行隐式转换,不需要我们另外处理,所以在 MySQL 上,基本不需要太过担心数据类型的问题,正因为这点它特别适合小白入门~~

更多的“副作用”可参考下图:

参考链接:https://help.aliyun.com/zh/maxcompute/user-guide/hive-compatible-data-type-edition

image.png

5、如何开启 Hive 兼容模式?

了解了 Hive 的正面作用和副作用之后,还是决定使用,就可以打开 Hive 开关尽情“享用”啦!

设置开关语法:

set odps.sql.hive.compatible=true; -- 打开Hive兼容模式。

使用方法,放在 SQL前面,和 SQL 一起执行,每一个设置命令作为一个独立的语句,用;结尾:

set odps.sql.hive.compatible=true;   --打开Hive兼容模式
SELECT xxx FROM xxx;

为了保证无差异,把 ODPS 2.0 的设置一同加上。

set odps.sql.type.system.odps2=true; --打开MaxCompute 2.0数据类型。
set odps.sql.decimal.odps2=true;     --打开Decimal 2.0数据类型。
set odps.sql.hive.compatible=true;   --打开Hive兼容模式。
SELECT xxx FROM xxx;

所以,开启 Hive 兼容模式最终得到的解决方案如下:

set odps.sql.type.system.odps2=true; --打开MaxCompute 2.0数据类型。
set odps.sql.decimal.odps2=true;     --打开Decimal 2.0数据类型。
set odps.sql.hive.compatible=true;   --打开Hive兼容模式。
SELECT FROM_UNIXTIME(1672538400),DATE_FORMAT(FROM_UNIXTIME(1672538400),'yyyyMMdd');

结果如下:
image.png

6、该场景下,能不能不开启 Hive 兼容模式?

肯定的!查看 MaxCompute 的官方文档可以看到以下片段:

DATE_FORMAT 函数链接:https://help.aliyun.com/zh/maxcompute/user-guide/date-format

image.png

MaxCompute 的DATE_FORMAT()函数总共支持4个类型的参数:DATE、DATETIME、TIMESTAMP 和 STRING。其中三个:DATE、DATETIME 和 STRING类型只能在 Hive 兼容模式下使用,还有一个:TIMESTAMP 可以在非 Hive 兼容模式下使用。

那么使用CAST(FROM_UNIXTIME(1672538400)AS TIMESTAMP)将数据类型转化为 TIMESTAMP 便可!

set odps.sql.type.system.odps2=true; --打开MaxCompute 2.0数据类型。
set odps.sql.decimal.odps2=true; 		 --打开Decimal 2.0数据类型。
set odps.sql.hive.compatible=false;  --关闭Hive兼容模式。
select FROM_UNIXTIME(1672538400),DATE_FORMAT(CAST(FROM_UNIXTIME(1672538400) AS TIMESTAMP),'yyyyMMdd');

返回结果如下:
image.png

7、为什么不是DATE_FORMAT(datetime, string)

在上面的描述过程中,不知道你是否留意到,其实还有一个问题没有解决?

FROM_UNIXTIME()函数,它在 Hive 兼容模式下的返回值为 STRING 类型,而在 ODPS 1.0 和 ODPS 2.0 数据类型版本的返回值为 DATETIME 类型。但是我在没有开启 Hive 兼容模式下,返回的报错却是 MaxCompute 不支持这个语法DATE_FORMAT(string, string),而不是DATE_FORMAT(datetime, string)

那么实际上非 Hive 兼容模式是返回 STRING 还是 DATETIME 呢?

为了回答这个疑问,我做了一个验证:测试验证 FROM_UNIXTIME()在不同的模式下返回的数据类型。

说明:

  • 时间戳1672538400转换为时间格式是2023-01-01 10:00:00
  • DATE()是 ODPS 2.0 才有的语法,需要打开 ODPS 2.0 开关,有的项目直接设置打开 ODPS2,但为了保险起见,这里再设置一下,你可以查看项目的相关配置是否有开启,如果开启则不需要再设置。
  • 查文档可知:FROM_UNIXTIME()在 Hive 兼容模式下返回 STRING,在非 Hive 兼容模式下返回 DATETIME;

【测试1】开启 Hive 兼容模式,FROM_UNIXTIME(1672538400)是否返回 STRING 类型?

set odps.sql.type.system.odps2=true; --打开MaxCompute 2.0数据类型。
set odps.sql.decimal.odps2=true;     --打开Decimal 2.0数据类型。
set odps.sql.hive.compatible=true;   --打开Hive兼容模式。
SELECT FROM_UNIXTIME(1672538400),FROM_UNIXTIME(1672538400)='2023-01-01 10:00:00';

返回结果如下,符合预期。

image.png

【测试2】关闭 Hive 兼容模式,FROM_UNIXTIME(1672538400)是否返回 DATETIME 类型?

set odps.sql.type.system.odps2=true; --打开MaxCompute 2.0数据类型。
set odps.sql.decimal.odps2=true;     --打开Decimal 2.0数据类型。
set odps.sql.hive.compatible=false;  --关闭Hive兼容模式。
SELECT FROM_UNIXTIME(1672538400),FROM_UNIXTIME(1672538400)='2023-01-01 10:00:00';

结果如下:

image.png

什么情况?也相等?通过FROM_UNIXTIME(1672538400)='2023-01-01 10:00:00'判断进行了隐式转换?既然不管等号右边是 STRING 还是 DATATIME,都返回 true。改个方式,使用DATE()辅助判断。

说明:DATE()函数传入的值是时间格式'yyyy-MM-dd'的字符串或者 DATETIME 类型才会返回日期值,如果是时间格式'yyyy-MM-dd hh:mi:ss'的字符串,返回空值。

【测试3】改用DATE()函数辅助判断:开启 Hive 兼容模式,DATE(FROM_UNIXTIME(1672538400))是否返回空值?

set odps.sql.type.system.odps2=true; --打开MaxCompute 2.0数据类型。
set odps.sql.decimal.odps2=true;     --打开Decimal 2.0数据类型。
set odps.sql.hive.compatible=true;   --关闭Hive兼容模式。
SELECT FROM_UNIXTIME(1672538400),DATE(FROM_UNIXTIME(1672538400));

结果如下,符合预期。

image.png

【测试4】改用DATE()函数辅助判断:关闭 Hive 兼容模式,DATE(FROM_UNIXTIME(1672538400))是否返回日期?

set odps.sql.type.system.odps2=true; --打开MaxCompute 2.0数据类型。
set odps.sql.decimal.odps2=true;     --打开Decimal 2.0数据类型。
set odps.sql.hive.compatible=false;   --关闭Hive兼容模式。
SELECT FROM_UNIXTIME(1672538400),DATE(FROM_UNIXTIME(1672538400));

结果如下,符合预期。

image.png

【补充测试】DATE('2023-01-01 10:00:00')DATE(CAST('2023-01-01 10:00:00' as datetime))返回的结果是否是空值和时间字段?

set odps.sql.type.system.odps2=true; --打开MaxCompute 2.0数据类型。
SELECT DATE('2023-01-01 10:00:00'),DATE(CAST('2023-01-01 10:00:00' AS DATETIME));

返回结果如下,符合预期。

image.png

以上通过间接的方式验证了在 MaxCompute 中,FROM_UNIXTIME()在 Hive 兼容模式下返回 STRING,在非 Hive 兼容模式下返回 DATETIME。

非 Hive 兼容模式下,FROM_UNIXTIME(1672538400)确实是返回的是 DATETIME 类型,那么就是 DATETIME 类型传入DATE_FORMAT()时,会被转换为 STRING 类型进行处理。

8、小结

解决 MaxCompute 不支持这个语法DATE_FORMAT(string, string)的方法本文提供了两种:

  • 方法1:开启 Hive 兼容模式
set odps.sql.type.system.odps2=true; --打开MaxCompute 2.0数据类型。
set odps.sql.decimal.odps2=true;     --打开Decimal 2.0数据类型。
set odps.sql.hive.compatible=true;   --打开Hive兼容模式。
SELECT FROM_UNIXTIME(1672538400),DATE_FORMAT(FROM_UNIXTIME(1672538400),'yyyyMMdd');
  • 方法2:显性修改传入FROM_UNIXTIME(1672538400)返回的数据类型
set odps.sql.type.system.odps2=true; --打开MaxCompute 2.0数据类型。
set odps.sql.decimal.odps2=true; 		 --打开Decimal 2.0数据类型。
set odps.sql.hive.compatible=false;  --关闭Hive兼容模式。
select FROM_UNIXTIME(1672538400),DATE_FORMAT(CAST(FROM_UNIXTIME(1672538400) AS TIMESTAMP),'yyyyMMdd');

另外,传递给DATE_FORMAT()的参数如果是 DATETIME 类型,会被隐性转换为 STRING 处理。





往期回顾:

阿里云大数据实战记录9:MaxCompute RAM 用户与授权
阿里云大数据实战记录8:拆开 json 的每一个元素,一行一个
阿里云大数据实战记录7:如何处理生产环境表单的重复数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/139035.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Qt-17】Qt调用matlab生成的dll库

matlab生成dll库 1、matlab示例代码 function BDCube(x,y)[x,y,z] cylinder(x,y);t1 hgtransform;s1 surf(3*x,3*y,4*z,Parent,t1);grid onview(3)shading interp end 2、matlab环境配置 首先检查自己的mcc编译器是否可用,输出以下命令: &#x…

如何在没有第三方.NET库源码的情况,调试第三库代码?

大家好,我是沙漠尽头的狼。 本方首发于Dotnet9,介绍使用dnSpy调试第三方.NET库源码,行文目录: 安装dnSpy编写示例程序调试示例程序调试.NET库原生方法总结 1. 安装dnSpy dnSpy是一款功能强大的.NET程序反编译工具,…

【Java 基础篇】Java线程安全与并发问题详解

多线程编程在Java中是一个常见的需求,它可以提高程序的性能和响应能力。然而,多线程编程也带来了一系列的线程安全与并发问题。在本文中,我们将深入探讨这些问题,以及如何解决它们,适用于Java初学者和基础用户。 什么…

【AI视野·今日NLP 自然语言处理论文速览 第三十六期】Wed, 20 Sep 2023

AI视野今日CS.NLP 自然语言处理论文速览 Wed, 20 Sep 2023 Totally 64 papers 👉上期速览✈更多精彩请移步主页 Daily Computation and Language Papers SlimPajama-DC: Understanding Data Combinations for LLM Training Authors Zhiqiang Shen, Tianhua Tao, Li…

原生js值之数据类型详解

js的数据类型 数据类型分类基本数据类型boolean:布尔类undefined:未定义的值null类型数值转换 NumberparseInt 转换整数 parseFloat转换浮点数 String类型特点如何转换成字符串模板字面量字符串插值模板字面量标签函数 symbol类型特性使用 BigInt类型复杂数据类型Object类属性与…

[杂谈]-八进制数

八进制数 文章目录 八进制数1、概述2、八进制数的表示2.1 八进制数2.2 以八进制计数2.3 二进制数补零 3、八进制到十进制转换4、十进制到八进制转换5、二进制到八进制转换示例6、八进制到二进制和十进制转换示例7、总结 1、概述 八进制编号系统是另一种使用基数为8计数系统&am…

【Stm32】【Lin通信协议】Lin通信点亮灯实验

Lin通信点亮灯实验 通过STM32的串口发送数据,然后通过串口转换模块将数据转换成LIN(Local Interconnect Network)协议,最终控制点亮灯。需要工程和入门资料的可以私信我,看到了马上回。 入门书本推荐: 一…

【C++面向对象侯捷下】2.转换函数 | 3.non-explicit-one-argument ctor

文章目录 operator double() const {} 歧义了 标准库的转换函数

exe文件运行后无输出直接闪退如何找解决办法

一.搜索栏搜事件查看器 二.点开windows日志下的应用程序 三.找到错误处 四.搜索异常代码 点开有错误的详细信息,直接用搜索引擎搜索这个异常代码能大致判断是什么问题,给了一个解决思路,不至于不知道到底哪里出了问题

AUTOSAR词典:CAN驱动Mailbox配置技术要点全解析

AUTOSAR词典:CAN驱动Mailbox配置技术要点全解析 前言 首先,请问大家几个小小问题,你清楚: AUTOSAR框架下的CAN驱动关键词定义吗?是不是有些总是傻傻分不清楚呢?CAN驱动Mailbox配置过程中有哪些关键配置参…

Angular变更检测机制

前段时间遇到这样一个 bug,通过一个 click 事件跳转到一个新页面,新页面迟迟不加载; 经过多次测试发现,将鼠标移入某个 tab ,页面就加载出来了。 举个例子,页面内容无法加载,但是将鼠标移入下图…

[面试] k8s面试题 2

文章目录 核心组件1.什么是 Kubernetes 中的控制器(Controller)?请提供一些常见的控制器类型。2.请解释一下 Kubernetes 中的 Ingress 是什么,以及它的作用。3.如何通过命令行在 Kubernetes 中创建一个 Pod?4.Stateful…

Pdf文件签名检查

如何检查pdf的签名 首先这里有一个已经签名的pdf文件&#xff0c;通过pdf软件可以看到文件的数字签名。 图1为签名后的文件&#xff0c;图2为签名后文件被篡改。 下面就是如何代码检查这里pdf文件的签名 1.引入依赖 <dependency><groupId>org.projectlombok<…

数据结构——单链表

目录 一.前言 二.链表表示和实现&#xff08;单链表&#xff09; 1.1 顺序表的优缺点 1.2 链表的概念及结构 1.3 打印函数 1.4 空间函数 1.5 尾插函数&#xff08;最最最麻烦的&#xff09; 1.5.1 尾插最关键部分&#xff01; 1.6 头插函数 1.7 尾删函数…

云流化:XR扩展现实应用发展的一个新方向!

扩展现实的发展已经改变了我们工作、生活和娱乐的方式&#xff0c;而且这才刚刚开始。扩展现实 (Extended reality, XR) 涵盖了沉浸式技术&#xff0c;包括虚拟现实、增强现实和混合现实。从游戏到虚拟制作再到产品设计&#xff0c;XR 使人们能够以前所未有的方式在计算机生成的…

#循循渐进学51单片机#指针基础与1602液晶的初步认识#not.11

1、把本节课的指针相关内容&#xff0c;反复学习3到5遍&#xff0c;彻底弄懂指针是怎么回事&#xff0c;即使是死记硬背也要记住&#xff0c;等到后边用的时候可以实现顿悟。学会指针&#xff0c;就是突破了C语言的一道壁垒。 2&#xff0c;1602所有的指令功能都应用一遍&#…

vue3——pixi初学,编写一个简单的小游戏,复制粘贴可用学习

pixi官网 小游戏效果 两个文件夹 一个index.html 一个data.js //data.js import { reactive } from "vue"; import { Sprite, utils, Rectangle, Application, Text, Graphics } from "pixi.js";//首先 先创建一个舞台 export const app new Applicat…

[Go疑难杂症]为什么nil不等于nil

现象 在日常开发中&#xff0c;可能一不小心就会掉进 Go 语言的某些陷阱里&#xff0c;而本文要介绍的 nil ≠ nil 问题&#xff0c;便是其中一个&#xff0c;初看起来会让人觉得很诡异&#xff0c;摸不着头脑。 先来看个例子&#xff1a; type CustomizedError struct {Err…

【面试必刷TOP101】 删除有序链表中重复的元素-I 删除有序链表中重复的元素-II

目录 题目&#xff1a;删除有序链表中重复的元素-I_牛客题霸_牛客网 (nowcoder.com) 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 题目&#xff1a;删除有序链表中重复的元素-II_牛客题霸_牛客网 (nowcoder…

摩尔信使MThings实用功能盘点

“冗长的用户手册”与“精简的交互设计”之间势必产生一条信息鸿沟&#xff0c;现在就来盘点一下摩尔信使MThings有哪些隐蔽而实用的功能。 01 数据配置类 一键刷新 功能&#xff1a;快速读取所有位数据、寄存器数据的当前数值。 操作&#xff1a;双击“数值”列表头。 一键…