Presto(Trino) 与 Hive SQL 语法及函数的一些不同

689 阅读5分钟

前言

在当今的大数据分析领域,Apache Hive 和 Presto(本文中 Presto 说的是 PrestoSQL,即后来的 Trino) 都是极为重要的工具,它们各自拥有独特的特点和优势,被广泛应用于处理和分析大规模数据集。Hive,作为Hadoop生态系统中的一个数据仓库工具,它将SQL查询能力带给了Hadoop,使得用户能够使用熟悉的SQL语法来查询和管理存储在Hadoop文件系统中的数据。而Trino,一个高性能、分布式的SQL查询引擎,以其快速的交互式查询能力而闻名。

尽管Hive和 Trino 都遵循SQL标准,允许用户执行 SELECT、GROUP BY、INSERT 等操作,但它们在SQL语法和函数实现上存在一些差异。这些差异可能源于它们的设计目标、优化策略等原因。了解这些差异对于数据工程师和分析师或者数据平台及引擎侧工程师来说至关重要,因为它们直接影响到查询的性能、结果的准确性以及开发和维护的复杂性。

在这篇文章中,我们将深入探讨 Trino 与Hive 在SQL语法及函数上的一些关键差异。我们将分析和比较它们在数据类型、函数支持、SQL语法等方面的不同之处。

数据类型方面

截屏2024-09-01 17.48.24.png

语法方面

1、order by 排序对 NULL 处理不同。trino中对 NULL 默认是 NULLS_LAST,而 hive 是NULL_FIRST。 在 trino 中,可以通过 ORDER BY expression [ ASC | DESC ] [ NULLS { FIRST | LAST } ] 兼容 hive。

2、LIMIT 支持不同。trino 中 limit 语法是 LIMIT { count | ALL } ,不支持 limit [offset,] rows

3、trino 中不支持 count distinct多列,即不支持 count(distinct a,b,c);

4、trino 中不支持 支持laterval view explode,但提供有相似功能的语法 Unnest ;

5、trino 中不支持字符串 uneacape;

6、trino 中数组下标从 1 开始,而 hive 中数据下标从 0 开始;

7、trino 中不支持数字开头的字段名表名别名等,而 hive 支持;

8、trino 中不支持 having 中使用select定义的别名;

9、trino 中不支持字符串双引号标识符;

10、trino 中不支持反引号标识符;

11、trino 中不支持 string、float类型,而提供同语义类型的 varchar、real;

12、trino 是强类型的语法引擎,而 hive 是弱类型的语法引擎,意思就是trino 不支持隐式类型转换,而 hive支持隐式类型转换。比如,trino 中不支持 1 + '1' 的表达式,而hive支持。

13、trino 中对于casewhen中不支持隐式类型转换;

14、trino 中对于子查询中不支持隐式类型转换;

15、trino 中不支持 double 标识符 D/d 标识,比如 trino 中不支持 1.5D 格式的 double 数值。

16、trino 中不支持 semi join,提供 inner join;

17、trino 中不支持 cluster by、distribute by 语法;

18、trino 中不支持 sort by语法;

函数方面

时间函数

1、trino 中没有 to_date 函数;

2、trino 中 from_unixtime 函数不支持字符串类型;

3、trino 中没有 last_day 函数;

4、trino 中没有unix_timestamp 函数;

5、trino 中没有 datediff 函数,但有date_diff 函数;

6、trino 中 month、year 函数不支持 varchar类型参数;

7、trino 中没有 date_sub 函数;

字符串函数

1、trino 中没有 ifnull,isnull,isnotnull 函数;

2、ttrino 中没有 instr,nvl 函数;

3、trino 中不支持concat 非字符串类型,而 hive支持;

4、trino 中sum、avg函数不支持字符串类型参数;

5、trino 中不支持 md5 函数,而 hive 支持;

6、trino 中不支持 regexp、rlike函数,但支持 regexp_like;

7、trino 中不支持字符串 uneacape;

计算函数

1、trino 中没有 div 函数;

2、trino 中没有 bigint、int、string等函数,如 bigint('5');

3、trino 中计算分位值的函数是 approx_percentile,而 hive 是 percentile_approx;

4、trino 中没有 == ! & | ^ 等函数;

5、trino 中没有 collect_list/collect_set 函数;

6、trino rank 函数返回值为bigint,而hive为int;

7、trino 不支持 int 类型除法divide函数返回double类型;

8、对于 sum 函数,spark、mr、trino的查询结果精度都不一致。可以通过在trino DoubleSumAggregation中的 double 的 +-*/ 用BigDecimal实现,可以解决trino每次查询结果不一致的问题,但BigDecimal的实现,会影响查询效率。

数组函数

1、trino 中获取数组、map 长度的函数是 cardinality,而hive中是 size;

2、trino 中没有 array 函数,如 array(1,2,3);

3、trino 中数组包含的函数是 contains,而hive是 array_contains;

JSON 函数

1、trino 从 json 中获取元素的函数 json_extract_scalar,在 hive 中为 get_json_object。

但需要注意的是,两者对嵌套 json 中里层 json 对象的获取规则不同,返回值不同。

其他函数

1、trino 中没有 locate 函数;

2、trino 中没有 str_to_map 函数;

3、trino 中 cast 函数不支持 cast(double/decimal to int);

4、trino 中 cast函数转化失败会报错,而hive是返回 null;

5、trino 中 substr、substring函数不支持数字类型参数,而hive支持;

最后

上面列举出了一些 trino 和 hive 在语法、函数等方面的差距,但并没有涵盖全部的不同。实际上,还存在大量的不同的语法、函数等。并且,即便是有同名的函数、语法,其用法和参数也未必相同,更重要的是,返回值和表现未必相同。

上面列举出的各种不同,应用在实际生产中,可以涵盖至少 80% 的 Trino SQL 兼容 Hive SQL 的场景。如果再加上在 Trino 中兼容 Hive 的用户自定义函数(UDF、UDAF、UDTF),预计覆盖率可以达到至少95% 的程度,对于从 Hive迁移至 Trino 的工作大有裨益。据说滴滴的线上 SQL 通过率达到了 97% ~ 99%。

不过,如果只是靠人为的寻找 trino 和 hive 在语法、函数等方面全部的不同,无异会是一个繁琐的、工作量巨大的工程。而 Trino 兼容 Hive 的方案,将在下一篇文章中呈现。


大数据小百科.jpg

欢迎关注我的公众号“**大数据小百科**”,原创技术文章第一时间推送。