Maxcompute-UNION数据类型对齐的方法
简介: 怎么对齐两段union脚本的数据类型
第1章 问题概述
1.1 UNION中隐式类型转换问题
近期参与的一个私有云项目要升级,因为maxcompute要升级到更新的版本,对之前的一些SQL写法有个更高的要求,就引出了这个union隐式转换的问题。运维同学扫描到内部的异常是:union.string.meet.non.string。
在ODPS某些模式中在union两侧对应列如果类型不同时会尝试隐式类型转换,其行为是一边为string,另一边为数字或datetime类型时,转为另一边的类型(string)。然而绝大多数的数据库或者开源生态而言,使用的都不是这种转换规则,比如hive,mysql等会优先转成string。这种不确定的转换规则有时候会很危险,如用户从hive往odps迁移时,可能会导致无声无息的精度损失,语义错误等。 ODPS2.0为了安全禁止此隐式类型转换(这也是目前oracle的默认行为),如果需要请使用CAST函数。(之前好好的,现在要报错了)所以现在项目组要求脚本作者检查自己脚本,明确要转到的类型,如果需要加入显式转换。
例:select * from (--(错误)
select a_bigint c1 from t1
union all
select a_string c1 from t2) x;
-- 如果希望结果c1为bigint类型(这是目前ODPS的行为),改为
select * from (--(正确)
select a_bigint c1 from t1
union all
select cast(a_string as bigint) c1 from t2) x;
-- 如果希望结果c1为string类型(这是目前HIVE的行为),改为
select * from (--(正确)
select cast(a_bigint as string) c1 from t1
union all
select a_string c1 from t2) x;
1.2 问题分析
因为还未升级,目前脚本也不会报错,maxcompute的异常我们也捕获不到,改造的压力有点纯靠肉眼识别了,着实有点难过。
错误示例:
select 123 as aa,0 as ab
from xlog
union ALL
select getdate() as aa,0 as ab
from xlog;
FAILED: ODPS-0130241:[4,8] Illegalunion operation - type mismatch for column 0 of UNION, left is BIGINT while right is DATETIME
--注释:这里的[4,8]是指第四行,第八个字符开始也就是getdate().
那怎么去快速的定位到是哪个字段呢?我翻了一下后台检索出来的上百个脚本,脚本代码在500-1000行之间居多,union 的数量在单个脚本中少则三五个,多的有二十几个。呆了一早上,毫无进展。
第2章 问题解决
简单的思考了一下,要想获得Union的两个表数据类型是否对齐,就得看下原来表结构中的数据类型,目标表结构的数据类型,还需看一下代码找到SQL逻辑执行后的数据类型,这样才能找到哪些字段数据类型不一致。
于是按照这个思路开始看,第一个脚本的代码就1000多行,union的表字段数量也是100多个,union还有6个。直接懵了,完全肉眼无法识别。一早上就这么过去了,不但一个没有搞定,还把自己搞烦了。
2.1 利用执行计划
一抽莫展之际,突然想到了执行计划。MaxCompute的执行计划,虽然会不会刚好会展示输出的数据类型呢?答案:会的。
explain
select 123 as aa,0 as ab
from xlog
;
Job Queueing...
job0 is root job
In Job job0:
root Tasks: M1
In Task M1:
Data source: mujiao.xlog
TS: mujiao.xlog
SEL: 123L aa, 0L ab
FS: output: Screen
schema:
aa (bigint)
ab (bigint)
OK
explain
select getdate() as aa,0 as ab
from xlog;
;
Job Queueing...
job0 is root job
In Job job0:
root Tasks: M1
In Task M1:
Data source: mujiao.xlog
TS: mujiao.xlog
SEL: 1655965081824 aa, 0L ab
FS: output: Screen
schema:
aa (datetime)
ab (bigint)
OK
我们看到在FS:output:Screen 下面是schema:aa(bigint),ab(bigint)。这就是我们可以利用的数据类型了。所以,我们可以把长脚本中的union一段一段的explain,然后截取这部分内容,比较多个schema的不同。
schema1: schema2:
aa (bigint) aa (datetime)
ab (bigint) ab (bigint)
这样就肉眼可视的发现其实union中两段SQL的字段aa是不同的。
2.2 其他问题
其他相关的一些问题:
1) 执行计划中的max_pt()函数无法在开发环境使用,因为开发环境没有分区,这个函数会直接报错。要么删除、注释这个函数,要么在表前面增加生产环境前缀。
2) 超长的SQL段,执行计划可能有几百行上千行,找不到最终的output。可以在日志中搜索“output: Screen”这段对应的就是最终的输出。
3) 太多的字段,肉眼无法判断哪些类型不一样的时候,建议在excel中来比较,利用excel的筛选能力,逐个数据类型筛选比较。
4) 执行计划在特别的情况下可能出不来,使用create table as创建一个临时表来识别SQL输出的数据类型,然后再desc表结构。不过每个字段都要给一个名称,在create table的时候,还有null这种写法也是需要cast后给一个明确的数据类型。
5) 日期转换,因为string到日期转换的格式化类型不是能猜出来的,建议实际看一下数据格式,不要猜测。否则只能线上运行后,报错才能排查出问题。
6) 对于Null值,可以cast(null as datetime)、cast(null as double)给字段赋值。
即便这些都可以,对于数百个长达几百行的脚本来说,这项工作都足以让你烦躁不安失去耐心。建议研发同学还是劳逸结合,再就是日后把这个工作变成一个习惯。一大段SQL的union,就直接先explain,别等报错一个一个看心烦。
最后,你会发现这一切的缘由还是我们的基础工作没有做好。既然是union一起的数据字段,理论数据类型和值域是一模一样的,怎么会出这种问题。标准化的数据应该是日期就是日期,数值就是数值,字符就是字符,不会数值存储成字符、日期存储成字符。显然,现在的痛苦还是来源于之前的工作缺失,做好每一步,后面会越来越轻松。
2.3 另外一个方法
后来跟研发同学要到了一个可以让warning信息显示出来的提示。
setodps.compiler.warning.disable=false;
sql running .....
WARNING:[4,8] implicit conversion from bigint to datetime,use cast function to suppress
这个warning会让所有的隐式转换都抛出来,在现场环境中,明显比我实际按照explain的方法判断出来的要多很多。这两种方法,在实际使用中该如何使用,大家可以自行判断。
祝大家好运!
Maxcompute-UNION数据类型对齐的方法的更多相关文章
- python常用数据类型内置方法介绍
熟练掌握python常用数据类型内置方法是每个初学者必须具备的内功. 下面介绍了python常用的集中数据类型及其方法,点开源代码,其中对主要方法都进行了中文注释. 一.整型 a = 100 a.xx ...
- 【转】C/C++ struct/class/union内存对齐
原文链接:http://www.cnblogs.com/Miranda-lym/p/5197805.html struct/class/union内存对齐原则有四个: 1).数据成员对齐规则:结构(s ...
- Ms SQLServer中的Union和Union All的使用方法和区别
Ms SQLServer中的Union和Union All的使用方法和区别 SQL UNION 操作符 UNION 操作符用于合并两个或多个 SELECT 语句的结果集. 请注意,UNION 内部的 ...
- CCS实现input和img水平对齐的方法
在网页制作中,常将 input 和 img 放在同一行,img标签总是比input高出一个头,非常难看. CCS实现input和img水平对齐的方法 同时给input和img添加vertical-al ...
- UILabel文本垂直顶部对齐的方法
也不知道为什么UILabel本身没有提供文本垂直顶部对齐的方法,真的有点晕.我们创建一个简单的UILabel来看看: [box type="info"] UILabel *myLa ...
- table下tbody滚动条与thead对齐的方法且每一列可以不均等
1 前言 table下tbody滚动条与thead对齐的方法,开始在tbody的td和thead的tr>td,对每一个Item加入百分比,结果是没对齐.也尝试了用bootstrap的col-md ...
- 迭代器-迭代对象-dir(a)可以查看该数据类型有多少种方法。range(10)在py3里就是一个迭代器,for循环实际就是迭代器的应用
迭代器 我们已经知道,可以直接作用于for循环的数据烈性有以下几种: 一类是集合数据类型,如list.tuple.dict.set.str,bytes等: 一类是generator,数据结构,包括生成 ...
- python-字典数据类型内置方法
字典数据类型内置方法(必考) 用途:存多个值,不通过索引取值,可以用关键字找到对应得值 定义方式:{}内以key:value的方式存储多个值,值与值之间用逗号隔开 lis = ['ruixing', ...
- 【msdn wpf forum翻译】TextBox中文本 中对齐 的方法
原文:[msdn wpf forum翻译]TextBox中文本 中对齐 的方法 原文链接:http://social.msdn.microsoft.com/Forums/en-US/wpf/threa ...
- 西数WD2T硬盘分区对齐的方法
新购一个西数2T硬盘,也就是绿盘的那种,淘宝500左右,支持高级格式化. 到手以后,分区格式化,前几天格式化完成以后,fdisk -l 发现如下文字 引用 Partition 1 does not s ...
随机推荐
- 记springBoot一直报Exception authenticating MongoCredential.
项目场景: 场景:继上回docker安装好了mongo,然后自己本地项目尝试搭建使用连接mongo 问题描述: 按照别人写的文章教程一步步操作,最后自己本地尝试连接查询,跳出这个用户权限不够,发生了套 ...
- Ubuntu14.04 apache2 配置 CGI(并测试:shell,可执行文件,python)
PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明 本文作为本人csdn blog的主站的备份.(Bl ...
- python面向对象编程(封装、隐藏)
一 封装 1.封装介绍封装是面向对象三大特性最核心的一个特性封装<----->整合2.将封装的属性进行隐藏操作1).如何隐藏:在属性名前加__前缀,就会实现一个对外隐藏属性效果该隐藏需要注 ...
- github 镜像地址
亲测可用的 github 镜像地址: https://hub.nuaa.cf , https://hub.fgit.cf
- 记录--JavaScript原型和原型链复习笔记
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 原型和原型链 1. 原型 每个JS对象一定对应一个原型对象,并从原型对象继承属性和方法 1.1 __proto__ 对象的__proto_ ...
- C# ASP.NET MVC 配置 跨域访问
在web.config文件中的 system.webServer 节点下 增加如下配置 <httpProtocol> <customHeader ...
- MySQL连接数超出最大值报错及修改
报错: create connection SQLException, url: jdbc:mysql://xx.xxx.x.xx:6306/hksk-cloud-mes?characterEncod ...
- C语言跨平台时间操作计算时间差
头文件 #pragma once #if defined(_WIN32) #include<sys/timeb.h> #if defined(__UNIX__)||defined(__AP ...
- Linux 基础命令和帮助命令
Linux命令 X Window 与命令行模式的切换 Linux默认的情况下会提供六个终端来让用户登录,切换的方式为使用[Ctrl+Alt+F1~F6]的组合键.系统会将[F1 ~ F6]命名为t ...
- 关于 ThreadLocal 你需要知道的几点
一.ThreadLocal是什么? 一个类对象类型,提供属线程本地变量,也就是同一个变量对不同线程保存了不同的值,但是和线程自身定义的自属变量不同. 通常以私有静态类型定义,用以保存特定线程特定状态属 ...