Apache Drill查询不需要预先了解您试图访问的实际数据,无论它的源系统或模式和数据类型如何。Apache Drill的最佳点是针对复杂数据的SQL查询工作负载:由各种类型的记录和字段组成的数据,而不是可识别的关系形式的数据(离散的行和列)。
当您提交查询时,Drill能够发现数据的形式。嵌套的数据格式,如JSON (JavaScript对象表示法)文件和Parquet文件不仅是可访问的:Drill提供了特殊的操作符和函数,您可以使用它们深入到这些文件中,并提出有趣的分析问题。
这些操作符和功能包括:
SQL查询开发人员需要充分了解数据,以便编写标识目标文件中感兴趣的值的查询。例如,为了可靠地请求select列表中的正确“列”,写入器需要知道记录由什么组成,以及它的数据类型。虽然这些数据值没有在源文件中显示为列,但是Drill将在结果集中返回它们,就好像它们在表中具有可预测的列形式一样。Drill还通过将数据视为“列”来优化查询,而不是读取和分析完整的记录。(Drill使用与商业列式MPP数据库类似的并行执行和优化功能。)
有了输入文件的基本知识,开发人员就需要知道如何使用Drill提供的SQL扩展以及如何使用它们“进入”嵌套数据。以下示例显示了如何针对JSON文件编写简单查询以及如何解压缩嵌套数据的有趣查询。这些示例说明了如何在标准SQL SELECT语句的上下文中使用Drill扩展。在大多数情况下,扩展使用标准JavaScript表示法引用层次结构中的数据元素。
本节中的示例对JSON数据文件进行操作。为了编写自己的查询,您需要了解以下文件中的基本数据类型:
检查Drill Web UI中的JSON文件是否具有以下配置设置(dfs存储插件配置):
“json” : {
“type” : “json”
}
复杂数据查询使用示例donuts.json文件。要下载此文件,请转到drill测试资源页面,在文件列表中找到donuts.json并下载。
这是文件中的第一个“记录”(0001)donuts.json。就Drill查询处理而言,此记录等效于表中的单个记录。
{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
"sales": 35,
"batters":
{
"batter":
[
{ "id": "1001", "type": "Regular" },
{ "id": "1002", "type": "Chocolate" },
{ "id": "1003", "type": "Blueberry" },
{ "id": "1004", "type": "Devil's Food" }
]
},
"topping":
[
{ "id": "5001", "type": "None" },
{ "id": "5002", "type": "Glazed" },
{ "id": "5005", "type": "Sugar" },
{ "id": "5007", "type": "Powdered Sugar" },
{ "id": "5006", "type": "Chocolate with Sprinkles" },
{ "id": "5003", "type": "Chocolate" },
{ "id": "5004", "type": "Maple" }
]
}
数据由映射,数组和嵌套数组组成。名称-值对和嵌入的名称-值对定义每个记录的内容。例如, type: donut是一张地图。在之下topping,成对的id和type值属于一个数组(在方括号内)。
一个非常简单的针对donuts.json文件的查询将返回五个“简单”列的值(这些列仅包含顶层数据:无嵌套数据):
apache drill> select id, type, name, ppu from dfs.`F:\大数据\drill\data\donuts.json`;
+------+-------+---------------+------+
| id | type | name | ppu |
+------+-------+---------------+------+
| 0001 | donut | Cake | 0.55 |
| 0002 | donut | Raised | 0.69 |
| 0003 | donut | Old Fashioned | 0.55 |
| 0004 | donut | Filled | 0.69 |
| 0005 | donut | Apple Fritter | 1.0 |
+------+-------+---------------+------+
5 rows selected (0.71 seconds)
请注意,这dfs是架构名称,文件的路径由反引号括起来,并且查询必须以分号结尾。
您可以使用标准的SQL子句(例如WHERE和ORDER BY)来详细说明这种简单的查询:
apache drill> select id, type from dfs.`F:\大数据\drill\data\donuts.json` where id>0 order by id limit 1;
+------+-------+
| id | type |
+------+-------+
| 0001 | donut |
+------+-------+
1 row selected (1.294 seconds)
您还可以使用标准语法来联接文件(或表,或文件和表):
apache drill> select tbl1.id, tbl1.type from dfs.`F:\大数据\drill\data\donuts.json` as tbl1 join dfs.`F:\大数据\drill\data\moredonuts.json` as tbl2 on tbl1.id=tbl2.id;
+------+-------+
| id | type |
+------+-------+
| 0001 | donut |
| 0002 | donut |
| 0003 | donut |
| 0004 | donut |
| 0005 | donut |
+------+-------+
5 rows selected (1.651 seconds)
还支持等效的USING语法和WHERE子句中的联接。
标准聚合函数可处理JSON数据。例如:
apache drill> select type, avg(ppu) as ppu_sum from dfs.`F:\大数据\drill\data\donuts.json` group by type;
+-------+---------+
| type | ppu_sum |
+-------+---------+
| donut | 0.696 |
+-------+---------+
1 row selected (3.867 seconds)
以下查询显示了如何访问记录中非平坦部分(例如topping)中的嵌套数据。要隔离并返回嵌套的数据,请使用[n]表示法,其中n的数字指向数组中的特定位置。数组使用从0开始的索引,因此topping[3]指向数组中的第四个元素topping,而不是第三个元素。
apache drill> select topping[3] as top from dfs.`F:\大数据\drill\data\donuts.json`;
+---------------------------------------+
| top |
+---------------------------------------+
| {"id":"5007","type":"Powdered Sugar"} |
| {"id":"5003","type":"Chocolate"} |
| {"id":"5004","type":"Maple"} |
| {"id":"5007","type":"Powdered Sugar"} |
| {} |
+---------------------------------------+
5 rows selected (2.135 seconds)
请注意,此查询为嵌套在文件段内的所有数据生成一列topping。编写的查询不会解压缩id和type名称/值对。还要注意使用别名作为列名。(没有别名,默认列名称将为EXPR$0。)
一些JSON文件将数组存储在数组中。如果您的数据具有此特征,则可以使用以下表示法探查内部数组:[n][n]
例如,假设JSON文件的一段如下所示:
...
group:
[
[1,2,3],
[4,5,6],
[7,8,9]
]
...
以下查询将返回6(第二个内部数组的第三个值)。
select group[1][2]
以下查询更进一步以提取JSON数据,从数组内部 选择特定值id和type数据值作为单独的列topping。该查询与上一个查询类似,但是它返回id和type值作为单独的列。
apache drill> select tbl.topping[3].id as record, tbl.topping[3].type as first_topping from dfs.`F:\大数据\drill\data\donuts.json` as tbl;
下面也可以跟官方文档描述有出入(官方文档表示字段前不加表名会报错)
select topping[3].id as record, topping[3].type as first_topping from dfs.`F:\大数据\drill\data\donuts.json`;
+--------+----------------+
| record | first_topping |
+--------+----------------+
| 5007 | Powdered Sugar |
| 5003 | Chocolate |
| 5004 | Maple |
| 5007 | Powdered Sugar |
| | |
+--------+----------------+
5 rows selected (0.175 seconds)