Skip to content
司马顿的博客
司马顿的博客

司马顿的博客

Drill, Spark, Hive的Window SQL函数对比

Posted on 2022年4月2日2022年4月4日 By 司马顿

关系型数据库的window函数我们都熟悉,主要用于统计分析目的,又叫做分析函数。

Apache组织下的一系列SQL引擎也都支持window函数,只是表现形式稍有不同。

我们简单测试下,测试数据同样来自这一份。测试的目的是简单求薪资(salary)的排名(rank)。

在Drill里加载数据最方便,因为无需定义schema,直接select csv文件就可以查询。用法如下。

apache drill (dfs.pyh)> select name,job,salary,rank() over(order by cast(salary as float) desc) as ranking from `people.csv` limit 10;
+---------------+--------------------------------------+---------+---------+
|     name      |                 job                  | salary  | ranking |
+---------------+--------------------------------------+---------+---------+
| Peyton U.O.   | Landscaper & Groundskeeper           | 29998.0 | 1       |
| Veronica R.R. | Electrician                          | 29997.0 | 2       |
| Rylee L.A.    | Brickmason & Blockmason              | 29996.0 | 3       |
| Emerson E.G.  | Pharmacist                           | 29995.0 | 4       |
| Zoe W.M.      | Veterinary Technologist & Technician | 29993.0 | 5       |
| Amiyah F.S.   | Clinical Laboratory Technician       | 29993.0 | 5       |
| Averie T.U.   | Cashier                              | 29993.0 | 5       |
| Gabriel V.V.  | Massage Therapist                    | 29992.0 | 8       |
| Jennifer L.P. | Hairdresser                          | 29987.0 | 9       |
| Lennox M.C.   | Pharmacist                           | 29983.0 | 10      |
+---------------+--------------------------------------+---------+---------+
10 rows selected (0.327 seconds)

如上,查询name, job, salary字段,并且按照salary字段排名,增加一列ranking,输出前10个结果。

上述也算是基本的SQL查询,唯一例外是需要用cast()函数改变下列的类型,因为Drill默认是没有类型的。

下面是Spark实现同样查询的方式。首先我们要加载数据,在加载的过程中使用inferSchema属性,也就是猜到数据类型。然后,导入spark的Window函数。最后,运用Window函数对dataframe进行统计。整个过程如下。

scala> val df = spark.read.format("csv").option("inferSchema", "true").option("header", "true").load("tmp/people.csv")

scala> import org.apache.spark.sql.functions._

scala> import org.apache.spark.sql.expressions.Window

scala> df.select("name","job","salary").withColumn("ranking",rank().over(Window.orderBy(desc("salary")) )).show(10,false);
+-------------+------------------------------------+-------+-------+
|name         |job                                 |salary |ranking|
+-------------+------------------------------------+-------+-------+
|Peyton U.O.  |Landscaper & Groundskeeper          |29998.0|1      |
|Veronica R.R.|Electrician                         |29997.0|2      |
|Rylee L.A.   |Brickmason & Blockmason             |29996.0|3      |
|Emerson E.G. |Pharmacist                          |29995.0|4      |
|Zoe W.M.     |Veterinary Technologist & Technician|29993.0|5      |
|Amiyah F.S.  |Clinical Laboratory Technician      |29993.0|5      |
|Averie T.U.  |Cashier                             |29993.0|5      |
|Gabriel V.V. |Massage Therapist                   |29992.0|8      |
|Jennifer L.P.|Hairdresser                         |29987.0|9      |
|Lennox M.C.  |Pharmacist                          |29983.0|10     |
+-------------+------------------------------------+-------+-------+
only showing top 10 rows

Spark加载的数据是有类型的,再加上它的所谓SQL是基于dataframe的,整个过程复杂一些,不如Drill那么直接。当然,上述用的是dataframe API,没有直接转换成SQL去查询。

再看看Hive,它对数据要求是强类型的。它用起来最麻烦,也很慢,相对来说可能安全点。

首先,我们创建一个数据表,指定数据类型(schema),再从HDFS上加载csv文件到这个表。然后直接运行Window函数查询结果。过程如下。

> create table ppl (
>   name string,
>   sex string,
>   born date,
>   zip int,
>   email string,
>   job string,
>   salary float
> )
> ROW FORMAT DELIMITED
> FIELDS TERMINATED BY ','
> STORED AS TEXTFILE;
No rows affected (0.609 seconds)

> LOAD DATA INPATH '/tmp/test/people.csv' OVERWRITE INTO TABLE ppl;
No rows affected (0.691 seconds)

> select name,job,salary,rank() over(order by salary desc) as ranking from ppl limit 10;
+----------------+---------------------------------------+----------+----------+
|      name      |                  job                  |  salary  | ranking  |
+----------------+---------------------------------------+----------+----------+
| Peyton U.O.    | Landscaper & Groundskeeper            | 29998.0  | 1        |
| Veronica R.R.  | Electrician                           | 29997.0  | 2        |
| Rylee L.A.     | Brickmason & Blockmason               | 29996.0  | 3        |
| Emerson E.G.   | Pharmacist                            | 29995.0  | 4        |
| Averie T.U.    | Cashier                               | 29993.0  | 5        |
| Amiyah F.S.    | Clinical Laboratory Technician        | 29993.0  | 5        |
| Zoe W.M.       | Veterinary Technologist & Technician  | 29993.0  | 5        |
| Gabriel V.V.   | Massage Therapist                     | 29992.0  | 8        |
| Jennifer L.P.  | Hairdresser                           | 29987.0  | 9        |
| Lennox M.C.    | Pharmacist                            | 29983.0  | 10       |
+----------------+---------------------------------------+----------+----------+
10 rows selected (1.374 seconds)

上述查询对比稍微总结下:

  • Drill使用最方便,无需事先定义schema。但是查询过程中,要手工使用cast函数,去转换数据类型,稍显麻烦。除此外它的SQL引擎使用起来比较直接。
  • Spark是需要schema的,它在加载数据时可以自动infer schema,所以也得到一个强类型的数据。但spark的SQL引擎要编程去使用,没那么方便。
  • Hive是强数据类型的,在创建表的时候就严格约束schema,再加载数据到表里。它的SQL引擎使用起来最直接。不过Hive SQL只是标准SQL的一个子集,功能没有Drill那么丰富。另外Hive也很慢。

就稳定性与安全性而言,无疑Hive最强。如果寻求使用的便利性和速度,应该是Drill胜出。如果是功能的丰富性,那还是Spark,因为它不止能处理结构化数据,还能处理非结构化数据、Streaming和机器学习。

Print this entry

博客 Apache Drill技术行业观点

文章导航

Previous post
Next post

Archives

  • 2022 年 9 月 (2)
  • 2022 年 8 月 (2)
  • 2022 年 7 月 (2)
  • 2022 年 6 月 (1)
  • 2022 年 5 月 (4)
  • 2022 年 4 月 (18)
  • 2022 年 3 月 (13)
  • 2022 年 2 月 (6)
  • 2022 年 1 月 (8)
  • 2021 年 12 月 (14)
  • 2021 年 11 月 (7)
  • 2021 年 10 月 (19)
  • 2021 年 9 月 (25)
  • 2021 年 8 月 (45)
  • 2021 年 7 月 (33)
  • 2021 年 6 月 (10)
  • 2021 年 3 月 (2)
  • 2021 年 2 月 (8)
  • 2021 年 1 月 (8)
  • 2020 年 12 月 (20)
  • 2020 年 11 月 (11)
  • 2020 年 10 月 (14)
  • 2020 年 9 月 (33)
  • 2020 年 8 月 (17)
  • 2020 年 7 月 (21)
  • 2020 年 6 月 (20)
  • 2020 年 5 月 (10)
  • 2020 年 4 月 (17)
  • 2020 年 3 月 (18)
  • 2020 年 2 月 (11)
  • 2020 年 1 月 (7)
  • 2019 年 12 月 (13)
  • 2019 年 11 月 (14)
  • 2019 年 10 月 (8)
  • 2019 年 9 月 (9)
  • 2019 年 8 月 (13)
  • 2019 年 7 月 (12)
  • 2019 年 6 月 (20)
  • 2019 年 5 月 (18)
  • 2019 年 4 月 (18)
  • 2019 年 3 月 (11)
  • 2019 年 2 月 (12)
  • 2019 年 1 月 (15)
  • 2018 年 12 月 (15)
  • 2018 年 11 月 (13)
  • 2018 年 10 月 (13)
  • 2018 年 9 月 (21)
  • 2018 年 8 月 (29)
  • 2018 年 7 月 (23)
  • 2018 年 6 月 (21)
  • 2018 年 5 月 (5)

标签

AI (24) Apache Drill (11) 加拿大 (21) 宇宙与人生 (19) 情感 (281) 技术 (75) 抑郁症 (68) 新冠病毒 (13) 汽车 (30) 生活 (333) 职场 (25) 行业观点 (60) 读书文艺 (48)
©2025 司马顿的博客 | WordPress Theme by SuperbThemes