Impala 教程
Set Up Some Basic .csv Tables
Impala 表指向已存的数据文件
查看 Impala 表结构
查询 Impala 表
数据加载与查询的例子
加载数据
查询例子
例子:检查表的内容
例子:聚合与连接
例子: 子查询, 聚合和连接
例子: INSERT 查询
将外部分区表指向 HDFS 目录结构
Impala 与 Hive 之间互为前后台
交叉连接和交叉连接操作的笛卡尔积(Cross Joins and Cartesian Products with the CROSS JOIN Operator)
使用 impala-shell 连接到 Impala
Impala 教程
本章节包括演示当软件安装之后,如何开始使用 Impala 的教程场景。着重于介绍载入数据的技术,因为当已经有数据在表中并且可以查询这些数据,你可以快速接触到更高级的 Impala 功能。
Note:
实际上,本教程教你从“0”开始到拥有期望的 Impala 表与数据。某些情况下,你可能需要从外部源下载其他文件,设置其他组件,修改命令或脚本来适应你自己的配置,或替换为你自己的例子数据(Where practical, the tutorials take you from “ground zero” to having the desired Impala tables and data. In some cases, you might need to download additional files from outside sources, set up additional software components, modify commands or scripts to fit your own configuration, or substitute your own sample data)。
请在开始本教程前预先安装好 Impala:
假如你已经有了 CDH 环境并且只需要安装 Impala,参照 Installing Cloudera Impala 中的安装步骤安装。如果没有配置Hive,请确保你已经安装了 Hive 以及它的 metastore 数据库。
仅用一次的测试环境,可以使用Cloudera QuickStart VM,它使用最小化配置,预先安装了所需软件和 Impala,包括 CentOS 6.3(64位)上的 CDH 和 Impala,可以实验后丢弃的(To set up Impala and all its prerequisites at once, in a minimal configuration that you can use for experiments and then discard, set up the Cloudera QuickStart VM, which includes CDH and Impala on CentOS 6.3 (64-bit). For more information, see the Cloudera QuickStart VM)。
继续阅读:
Set Up Some Basic .csv Tables
Point an Impala Table at Existing Data Files
Describe the Impala Table
Query the Impala Table
Data Loading and Querying Examples
Attaching an External Partitioned Table to an HDFS Directory Structure
Switching Back and Forth Between Impala and Hive
Cross Joins and Cartesian Products with the CROSS JOIN Operator
Connecting to Impala through impala-shell
Set Up Some Basic .csv Tables
本节演示如何创建一些非常小的表,适合初次使用的用户实验 Impala SQL 功能。 TAB1 和 TAB2 从 HDFS 文件中载入数据。TAB1 中的部分数据复制到 TAB3 中。
可以把你想查询的数据放入 HDFS 中。想开始这一过程,先在你的 HDFS 用户目录下创建一个或多个子目录。每个表中的数据存放在单独的子目录里。用你自己的用户名替换掉下面命令中的 cloudera 。这个例子使用 mkdir 中的 -p 选项,这样如果不存在必要的父目录中则自动创建(注:可以临时取消hdfs验证权限的设置,admin console -> hdfs1 -> Configuration -> View and Edit -> Uncheck “Check HDFS Persmissions”,重启服务,这样随意用户都可以创建目录)。
whoamicloudera
hdfs dfs -ls /user
Found 3 items
drwxr-xr-x - cloudera cloudera 0 2013-04-22 18:54 /user/cloudera
drwxrwx— - mapred mapred 0 2013-03-15 20:11 /user/history
drwxr-xr-x - hue supergroup 0 2013-03-15 20:10 /user/hive
$ hdfs dfs -mkdir -p /user/cloudera/sample_data/tab1 /user/cloudera/sample_data/tab2
这里有两个表 TAB1 和 TAB2 的测试数据。
把下面的内容复制到你本地文件系统的 .csv 文件里:
tab1.csv:
1,true,123.123,2012-10-24 08:55:00
2,false,1243.5,2012-10-25 13:40:00
3,false,24453.325,2008-08-22 09:33:21.123
4,false,243423.325,2007-05-12 22:32:21.33454
5,true,243.325,1953-04-22 09:11:33
tab2.csv:
1,true,12789.123
2,false,1243.5
3,false,24453.325
4,false,2423.3254
5,true,243.325
60,false,243565423.325
70,true,243.325
80,false,243423.325
90,true,243.325
使用类似下面的命令将两个 .csv 文件放入单独的 HDFS 目录中,这里使用了Impala Demo VM 中的可用路径:
hdfsdfs−puttab1.csv/user/cloudera/sampledata/tab1
hdfs dfs -ls /user/cloudera/sample_data/tab1
Found 1 items
-rw-r–r– 1 cloudera cloudera 192 2013-04-02 20:08 /user/cloudera/sample_data/tab1/tab1.csv
hdfsdfs−puttab2.csv/user/cloudera/sampledata/tab2
hdfs dfs -ls /user/cloudera/sample_data/tab2
Found 1 items
-rw-r–r– 1 cloudera cloudera 158 2013-04-02 20:09 /user/cloudera/sample_data/tab2/tab2.csv
每个数据文件的名称不重要。事实上,当 Impala 第一次检测数据目录的内容时,它认为目录下的所有文件都是表中的数据文件,无论目录下有多少文件,无论什么样的文件名。
要了解你的 HDFS 文件系统中什么目录可用,不同的目录和文件都有什么权限,执行 hdfs dfs -ls / 并沿着看到的目录树一直执行 -ls 操作。
使用 impala-shell 命令创建表,可以用交互式创建,也可以用 SQL 脚本。
下面的例子演示创建了三个表。每个表中的列都使用了不同的数据类型,如 Boolean 或 integer。 例子还包括了如何格式数据的命令,例如列以逗号分隔,这样从从 .csv 文件导入数据。我们已经有了存放在 HDFS 目录树中的包含数据的 .csv 文件,我们(为表)指定了包含对应 .csv 文件的路径位置。Impala 认为这些目录下的所有文件里的所有数据都是表里的数据。
DROP TABLE IF EXISTS tab1;
– EXTERNAL子句表示数据位于 Impala 数据文件中央位置之外
– 并且 Impala 中表删除后,原始数据文件仍然存在
– 我们假定 LOCATION 子句中指定的目录是存在的
CREATE EXTERNAL TABLE tab1
(
id INT,
col_1 BOOLEAN,
col_2 DOUBLE,
col_3 TIMESTAMP
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘,’
LOCATION ‘/user/cloudera/sample_data/tab1’;
DROP TABLE IF EXISTS tab2;
– TAB2 同 TAB1 一样都是外部表
CREATE EXTERNAL TABLE tab2
(
id INT,
col_1 BOOLEAN,
col_2 DOUBLE
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘,’
LOCATION ‘/user/cloudera/sample_data/tab2’;
DROP TABLE IF EXISTS tab3;
– 不使用 EXTERNAL 子句表示数据统一由 Impala 管理
– 这里不再在创建表时候读取已存在的数据文件,而是创建表之后再载入数据
CREATE TABLE tab3
(
id INT,
col_1 BOOLEAN,
col_2 DOUBLE,
month INT,
day INT
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘,’;
注意:这些 CREATE TABLE 语句能成功执行是一个重要的验证步骤,这确保你的 Hive metastore 和 HDFS 权限都配置正确了。假如你在执行 CREATE TABLE 语句时有任何错误:
请确认你按照 Installing Cloudera Impala 中的安装说明正确完成
请确认 hive.metastore.warehouse.dir 属性指向了一个Impala 可写的目录。该目录的所有者应当是 hive:hive,而 impala 用户应当是 hive 组的成员
假如在 Cloudera Manager 界面中和 Hive shell 中的 hive.metastore.warehouse.dir 的值不同,你需要为 Hive 分配以 “gateway” 角色运行的 impalad 主机(designate the hosts running impalad with the”gateway” role for Hive),并部署客户端配置文件到这些主机上(deploy the client configuration files to those hosts)。
Impala 表指向已存的数据文件
一个设置 Impala 访问数据的方便的方式是使用外部(external)表。数据已经存在于 HDFS 上的一组文件里,只需要把 Impala 表指向包含这些文件的目录即可。例如,你可以在 impala-shell 里运行类似下面内容的 *.sql 文件,来创建一个 Impala 表访问 Hive 中使用的已存在的数据文件:
注意:
在之前的 Impala beta 版里,本教程中的例子需要在 Hive 中执行 CREATE TABLE 命令。自 Impala 0.7 以后,可以在 Impala 中执行 CREATE TABLE 语句,因此现在教程里使用 Impala 执行 CREATE TABLE语句。
下面例子设置了 2 个表,使用了 Impala Demo VM 中的路径与例子数据。因为历史原因,数据实际存放在 HDFS 中 /user/hive 目录下,尽管这数据实际上是被 Impala 而不是 Hive 管理。当我们创建了一个外部表,我们指定了包含一个或多个文件的目录,Impala 会查询该目录下所有文件的所有内容。下面是我们如何检查 HDFS 文件系统中的目录与文件:
hdfsdfs−ls/user/hive/tpcds/customerFound1items−rw−r–r–1clouderasupergroup132093722013−03−2218:09/user/hive/tpcds/customer/customer.dat
hdfs dfs -cat /user/hive/tpcds/customer/customer.dat | more
1|AAAAAAAABAAAAAAA|980124|7135|32946|2452238|2452208|Mr.|Javier|Lewis|Y|9|12|1936|CHILE||Javier.
Lewis@VFAxlnZEvOx.org|2452508|
2|AAAAAAAACAAAAAAA|819667|1461|31655|2452318|2452288|Dr.|Amy|Moses|Y|9|4|1966|TOGO||Amy.Moses@Ov
k9KjHH.com|2452318|
3|AAAAAAAADAAAAAAA|1473522|6247|48572|2449130|2449100|Miss|Latisha|Hamilton|N|18|9|1979|NIUE||La
tisha.Hamilton@V.com|2452313|
4|AAAAAAAAEAAAAAAA|1703214|3986|39558|2450030|2450000|Dr.|Michael|White|N|7|6|1983|MEXICO||Micha
el.White@i.org|2452361|
5|AAAAAAAAFAAAAAAA|953372|4470|36368|2449438|2449408|Sir|Robert|Moran|N|8|5|1956|FIJI||Robert.Mo
ran@Hh.edu|2452469|
…
下面是 customer_setup.sql 脚本的内容:
–
– store_sales fact table and surrounding dimension tables only
create database tpcds;
use tpcds;
drop table if exists customer;
create external table customer
(
c_customer_sk int,
c_customer_id string,
c_current_cdemo_sk int,
c_current_hdemo_sk int,
c_current_addr_sk int,
c_first_shipto_date_sk int,
c_first_sales_date_sk int,
c_salutation string,
c_first_name string,
c_last_name string,
c_preferred_cust_flag string,
c_birth_day int,
c_birth_month int,
c_birth_year int,
c_birth_country string,
c_login string,
c_email_address string,
c_last_review_date string
)
row format delimited fields terminated by ‘|’
location ‘/user/hive/tpcds/customer’;
drop table if exists customer_address;
create external table customer_address
(
ca_address_sk int,
ca_address_id string,
ca_street_number string,
ca_street_name string,
ca_street_type string,
ca_suite_number string,
ca_city string,
ca_county string,
ca_state string,
ca_zip string,
ca_country string,
ca_gmt_offset float,
ca_location_type string
)
row format delimited fields terminated by ‘|’
location ‘/user/hive/tpcds/customer_address’;
使用下面命令运行脚本:
impala-shell -i localhost -f customer_setup.sql
注意:
目前的 impala-shell 要求交互是查询的命令必须是单行的,因此你测试上面命令时,或者把它保存为一个 .sql 文件,使用 -f 选项作为脚本运行,或者在 impala-shell 执行前把每个命令复制为一行。
查看 Impala 表结构
现在你已经更新了 Impala 缓存的数据库元数据,接下来你可以确认目标表可以被 Impala 访问,并检查其中一个表的属性。我们是在 default 数据库中创建的这些表。假如这些表不在 default 数据库,我们可以执行 “use db_name” 命令切换到我们之前测试和查询的表所在的数据库。我们也可以在表名前加上数据库名来标识表,例如 default.customer 和 default.customer_name
[impala-host:21000] > show databases
Query finished, fetching results …
default
Returned 1 row(s) in 0.00s
[impala-host:21000] > show tables
Query finished, fetching results …
customer
customer_address
Returned 2 row(s) in 0.00s
[impala-host:21000] > describe customer_address
+——————+——–+———+
| name | type | comment |
+——————+——–+———+
| ca_address_sk | int | |
| ca_address_id | string | |
| ca_street_number | string | |
| ca_street_name | string | |
| ca_street_type | string | |
| ca_suite_number | string | |
| ca_city | string | |
| ca_county | string | |
| ca_state | string | |
| ca_zip | string | |
| ca_country | string | |
| ca_gmt_offset | float | |
| ca_location_type | string | |
+——————+——–+———+
Returned 13 row(s) in 0.01
查询 Impala 表
你可以查询包含着表中的数据。Impala 根据你集群的配置协调单个节点或多个节点执行该查询,没有执行 MapReduce 作业进行中间处理的开销。
有以下不同的方式在 Impala 执行查询:
在 impala-shell 中以交互式模式执行命令:
impala−shell−iimpala−hostConnectedtolocalhost:21000[impala−host:21000]>selectcount(∗)fromcustomeraddress;50000Returned1row(s)in0.37s通过包含着文件中的一组命令:
impala-shell -i impala-host -f myquery.sql
Connected to localhost:21000
50000
Returned 1 row(s) in 0.19s
通过 传递到 impala-shell 中的单个命令。查询执行、返回结果、退出 impala-shell。请确保最好用单引号引起了命令,这样来避免 shell 扩展字符如 * 是哟内的问题(Make sure to quote the command, preferably with single quotation marks to avoid shell expansion of characters such as *)。
$ impala-shell -i impala-host -q ‘select count(*) from customer_address’
Connected to localhost:21000
50000
Returned 1 row(s) in 0.29s
数据加载与查询的例子
本节演示如何创建一些可以被 impala shell 查询的表并加载数据。
加载数据
加载数据包括:
建立数据集。本例中使用 .csv 文件
创建准备加载数据的表
加载数据到创建的表中
查询例子
为了运行这些查询例子,应先创建一个文件 query.sql,并把每个查询复制粘贴到文件里,然后在 impala shell 中运行 query.sql 文件。例如,在 impala 主机上使用下面命令执行 query.sql:
impala-shell.sh -i impala-host -f query.sql
下面的例子和结果假定你已经把例子数据加载到前面描述的表中。
例子:检查表的内容
让我们从检验表中是否包含了我们期待的数据开始。因为 Impala 通常处理包含成千上万行数据的表,所以检查未知大小的表时,应在最终查询里使用 Limit 子句以避免大量的不必要的输出(假如在 impala-shell 交互式查询环境中开始显示非期待的数据,使用 Ctrl-C 取消该查询)
SELECT * FROM tab1;
SELECT * FROM tab2;
SELECT * FROM tab2 LIMIT 5;
结果:
+—-+——-+————+——————————-+
| id | col_1 | col_2 | col_3 |
+—-+——-+————+——————————-+
| 1 | true | 123.123 | 2012-10-24 08:55:00 |
| 2 | false | 1243.5 | 2012-10-25 13:40:00 |
| 3 | false | 24453.325 | 2008-08-22 09:33:21.123000000 |
| 4 | false | 243423.325 | 2007-05-12 22:32:21.334540000 |
| 5 | true | 243.325 | 1953-04-22 09:11:33 |
+—-+——-+————+——————————-+
+—-+——-+—————+
| id | col_1 | col_2 |
+—-+——-+—————+
| 1 | true | 12789.123 |
| 2 | false | 1243.5 |
| 3 | false | 24453.325 |
| 4 | false | 2423.3254 |
| 5 | true | 243.325 |
| 60 | false | 243565423.325 |
| 70 | true | 243.325 |
| 80 | false | 243423.325 |
| 90 | true | 243.325 |
+—-+——-+—————+
+—-+——-+———–+
| id | col_1 | col_2 |
+—-+——-+———–+
| 1 | true | 12789.123 |
| 2 | false | 1243.5 |
| 3 | false | 24453.325 |
| 4 | false | 2423.3254 |
| 5 | true | 243.325 |
+—-+——-+———–+
例子:聚合与连接
SELECT tab1.col_1, MAX(tab2.col_2), MIN(tab2.col_2)
FROM tab2 JOIN tab1 USING (id)
GROUP BY col_1 ORDER BY 1 LIMIT 5;
结果:
+——-+—————–+—————–+
| col_1 | max(tab2.col_2) | min(tab2.col_2) |
+——-+—————–+—————–+
| false | 24453.325 | 1243.5 |
| true | 12789.123 | 243.325 |
+——-+—————–+—————–+
例子: 子查询, 聚合和连接
SELECT tab2.*
FROM tab2,
(SELECT tab1.col_1, MAX(tab2.col_2) AS max_col2
FROM tab2, tab1
WHERE tab1.id = tab2.id
GROUP BY col_1) subquery1
WHERE subquery1.max_col2 = tab2.col_2;
结果:
+—-+——-+———–+
| id | col_1 | col_2 |
+—-+——-+———–+
| 1 | true | 12789.123 |
| 3 | false | 24453.325 |
+—-+——-+———–+
例子: INSERT 查询
INSERT OVERWRITE TABLE tab3
SELECT id, col_1, col_2, MONTH(col_3), DAYOFMONTH(col_3)
FROM tab1 WHERE YEAR(col_3) = 2012;
查询 TAB3 检查结果:
SELECT * FROM tab3;
Results:
+—-+——-+———+——-+—–+
| id | col_1 | col_2 | month | day |
+—-+——-+———+——-+—–+
| 1 | true | 123.123 | 10 | 24 |
| 2 | false | 1243.5 | 10 | 25 |
+—-+——-+———+——-+—–+
将外部分区表指向 HDFS 目录结构
本教程演示如何在 HDFS 中设置目录树,将数据分局放置到最低级的子目录,然后使用 Impala 外部表从他们原始位置查询数据。
教程中使用包含 web 日志数据的表,日志数据使用单独的year、month、day、host子目录。为了简化问题,我们使用少量的包含相同数据的 CSV 文件放到到不同的分区里。
首先,我们为 CSV 数据创建一个 Impala 分区表,并查看底层的 HDFS 目录结构以理解目录结构方便在 HDFS 其他位置重建。列 field1,field2, field3 对应 CSV 数据文件中的内容。Year、month、day、host对应表中的子目录,不在 CSV 文件内容中。这些列都使用 STRING 类型,这样我们可以生成包含前导零的相同长度的目录名。
create database external_partitions;
use external_partitions;
create table logs (field1 string, field2 string, field3 string)
partitioned by (year string, month string , day string, host string)
row format delimited fields terminated by ‘,’;
insert into logs partition (year=”2013”, month=”07”, day=”28”, host=”host1”) values (“foo”,”foo”,”foo”);
insert into logs partition (year=”2013”, month=”07”, day=”28”, host=”host2”) values (“foo”,”foo”,”foo”);
insert into logs partition (year=”2013”, month=”07”, day=”29”, host=”host1”) values (“foo”,”foo”,”foo”);
insert into logs partition (year=”2013”, month=”07”, day=”29”, host=”host2”) values (“foo”,”foo”,”foo”);
insert into logs partition (year=”2013”, month=”08”, day=”01”, host=”host1”) values (“foo”,”foo”,”foo”);
返回 Linux shell,我们检查下 HDFS 目录结构(你的 Impala 数据目录可能在不同的位置;因为历史原因, 数据目录一般在 HDFS 目录 /user/hive/warehouse 下) 。我们使用 hdfs dfs -ls 目录查看对应着每一个分区列的嵌套子目录,每一级别对应着分区列的不同值(名称中包含=)的单独的子目录。当到达最底层的子目录,使用 hdfs dfs -cat 命令查看数据文件,可以看到由 Impala 中 INSERT 语句产生的 CSV-格式的数据。
hdfsdfs−ls/user/impala/warehouse/externalpartitions.dbFound1itemsdrwxrwxrwt−impalahive02013−08−0712:24/user/impala/warehouse/externalpartitions.db/logs
hdfs dfs -ls /user/impala/warehouse/external_partitions.db/logs
Found 1 items
drwxr-xr-x - impala hive 0 2013-08-07 12:24 /user/impala/warehouse/external_partitions.db/logs/year=2013
hdfsdfs−ls/user/impala/warehouse/externalpartitions.db/logs/year=2013Found2itemsdrwxr−xr−x−impalahive02013−08−0712:23/user/impala/warehouse/externalpartitions.db/logs/year=2013/month=07drwxr−xr−x−impalahive02013−08−0712:24/user/impala/warehouse/externalpartitions.db/logs/year=2013/month=08
hdfs dfs -ls /user/impala/warehouse/external_partitions.db/logs/year=2013/month=07
Found 2 items
drwxr-xr-x - impala hive 0 2013-08-07 12:22 /user/impala/warehouse/external_partitions.db/logs/year=2013/month=07/day=28
drwxr-xr-x - impala hive 0 2013-08-07 12:23 /user/impala/warehouse/external_partitions.db/logs/year=2013/month=07/day=29
hdfsdfs−ls/user/impala/warehouse/externalpartitions.db/logs/year=2013/month=07/day=28Found2itemsdrwxr−xr−x−impalahive02013−08−0712:21/user/impala/warehouse/externalpartitions.db/logs/year=2013/month=07/day=28/host=host1drwxr−xr−x−impalahive02013−08−0712:22/user/impala/warehouse/externalpartitions.db/logs/year=2013/month=07/day=28/host=host2
hdfs dfs -ls /user/impala/warehouse/external_partitions.db/logs/year=2013/month=07/day=28/host=host1
Found 1 items
-rw-r–r– 3 impala hive 12 2013-08-07 12:21 /user/impala/warehouse/external_partiti
ons.db/logs/year=2013/month=07/day=28/host=host1/3981726974111751120–8907184999369517436_822630111_data.0
$ hdfs dfs -cat /user/impala/warehouse/external_partitions.db/logs/year=2013/month=07/day=28/\
host=host1/3981726974111751120–8 907184999369517436_822630111_data.0
foo,foo,foo
还是在Linux shell 中,我们使用 hdfs dfs -mkdir 在 Impala 控制的 HDFS 目录之外创建几个数据目录(本例中是 /user/impala/warehouse ,可能与你的情况不同)。根据你系统配置的不同,你可能需要登录到具有 HDFS 目录树写权限的用户下;例如下面是登录到 hdfs 用户下执行的:
hdfsdfs−mkdir−p/user/impala/data/logs/year=2013/month=07/day=28/host=host1
hdfs dfs -mkdir -p /user/impala/data/logs/year=2013/month=07/day=28/host=host2
hdfsdfs−mkdir−p/user/impala/data/logs/year=2013/month=07/day=28/host=host1
hdfs dfs -mkdir -p /user/impala/data/logs/year=2013/month=07/day=29/host=host1
$ hdfs dfs -mkdir -p /user/impala/data/logs/year=2013/month=08/day=01/host=host1
我们创建一个与之前使用的插入语句的数据不同的小的 CSV 文件,复制到将用作 Impala 分区的子目录下
cat>dummylogdatabar,baz,bletch
hdfs dfs -mkdir -p /user/impala/data/external_partitions/year=2013/month=08/day=01/host=host1
hdfsdfs−mkdir−p/user/impala/data/externalpartitions/year=2013/month=07/day=28/host=host1
hdfs dfs -mkdir -p /user/impala/data/external_partitions/year=2013/month=07/day=28/host=host2
hdfsdfs−mkdir−p/user/impala/data/externalpartitions/year=2013/month=07/day=29/host=host1
hdfs dfs -put dummy_log_data /user/impala/data/logs/year=2013/month=07/day=28/host=host1
hdfsdfs−putdummylogdata/user/impala/data/logs/year=2013/month=07/day=28/host=host2
hdfs dfs -put dummy_log_data /user/impala/data/logs/year=2013/month=07/day=29/host=host1
$ hdfs dfs -put dummy_log_data /user/impala/data/logs/year=2013/month=08/day=01/host=host1
返回 impala-shell ,我们把原来的 Impala 管理表移动到一边,创意建一个新的包含 LOCATION 子句指向刚刚创建的分区子目录和数据文件的外部表。
use external_partitions;
alter table logs rename to logs_original;
create external table logs (field1 string, field2 string, field3 string)
partitioned by (year string, month string, day string, host string)
row format delimited fields terminated by ‘,’
location ‘/user/impala/data/logs’;
因为在整个数据生命周期中分区子目录和数据文件都存在(Because partition subdirectories and data files come and Go during the data lifecycle),你必须在 Impala 承认它们包含数据文件文件之前使用 ALTER TABLE 语句标识每一个分区。
alter table logs add partition (year=”2013”,month=”07”,day=”28”,host=”host1”)
alter table logs add partition (year=”2013”,month=”07”,day=”28”,host=”host2”);
alter table logs add partition (year=”2013”,month=”07”,day=”29”,host=”host1”);
alter table logs add partition (year=”2013”,month=”08”,day=”01”,host=”host1”);
当数据文件被手工添加、删除或修改后,为这个表执行一个 REFRESH 语句是一个安全的做法。然后数据就可以查询了。SELECT * 语句显示源于我们普通的 CSV 文件、复制到每一个分区下的的数据被认可了。尽管这时候只有几条数据,下面的测试查询中我们使用 LIMIT 子句以防有比我们预期的多的数据:
refresh logs;
select * from logs limit 100;
+——–+——–+——–+——+——-+—–+——-+
| field1 | field2 | field3 | year | month | day | host |
+——–+——–+——–+——+——-+—–+——-+
| bar | baz | bletch | 2013 | 07 | 28 | host1 |
| bar | baz | bletch | 2013 | 08 | 01 | host1 |
| bar | baz | bletch | 2013 | 07 | 29 | host1 |
| bar | baz | bletch | 2013 | 07 | 28 | host2 |
+——–+——–+——–+——+——-+—–+——-+
Impala 与 Hive 之间互为前后台
有时候你会发现,切换到 Hive 执行下数据加载或转换操作比较方便,特别是处理如 RCFile, SequenceFile, 和 Avro 等这些 Impala 暂时只支持查询不支持写入的数据文件格式
无论你在 Hive 中 create, drop, 或 alter 了一个表或其他对象,当切换回 impala-shell 时,立即执行一个 INVALIDATE METADATA 语句,这样 Impala 才会承认新增或修改的对象。
无论你在 Hive 中 load, insert, 或 change 了现存表中的数据 (乃至直接通过 HDFS 操作如 hdfs 命令),当切换回 impala-shell 时,立即执行 REFRESH table_name 语句,这样 Impala 才会承认新增或修改的数据。
关于 REFRESH 语句处理过程的演示,可以查看在 Impala 中创建 RCFile 和 SequenceFile 表,通过 Hive 加载数据,通过 Impala 查询数据的例子。 参见 Using the RCFile File Format with Impala Tables 和 Using the SequenceFile File Format with Impala Tables 。
关于 INVALIDATE METADATA 语句处理过程的演示,可以查看在 Hive 中创建 Avro 表并加载数据,通过Impala查询的例子,参见Using the Avro File Format with Impala Tables。
注意:
从 Impala 1.2 开始才支持 UDF(用户定义函数),之前的版本不支持。一些以前只能在 Hive 中执行的 INSERT … SELECT 转换现在可以在 Impala 中执行。参见 User-Defined Functions for Impala 了解详细信息。
在 Impala 1.2 之前,需要在每一个你需要连接和执行查询的 Impala 节点上都执行 REFRESH 和 INVALIDATE METADATA 语句。在 Impala 1.2 及以上版本,在每一轮 Hive 中的 DDL 和 ETL 操作之后,当你在任一 Impala 节点上运行这两个语句时,运行结果会广播到集群的所有节点上, 这使得这两个语句成为一个真正的单步操作。
交叉连接和交叉连接操作的笛卡尔积(Cross Joins and Cartesian Products with the CROSS JOIN Operator)
原来 Impala 限制连接查询中连接操作两侧的表的列必须至少有一个相等条件。Impala 通常处理的都是巨大的表,任何编码错误的查询可能产生一个完整的笛卡尔积结果集,会消耗大量的集群资源。
在 Impala 1.2.2 以上版本,可以在查询中使用交叉连接(CROSS JOIN)操作来解除这一限制。你仍然不能移除查询中所有的 WHERE 子句形成类似 SELECT * FROM t1 JOIN t2 to produce all 的语句来产生所有表中所有列的组合。但你可以使用交叉连接(CROSS JOIN)操作去明确的请求笛卡尔积。通常这一操作被用于笛卡尔积仍能放到单个 Impala 节点的内存里的小表。
下面的例子使用了一些其中的人物互相战斗的漫画书里的数据(The following example sets up data for use in a series of comic books where characters battle each other)。首先,我们执行一个等值查询,只允许相同时间和相同星球的人物人物相遇( At first, we use an equijoin query, which only allows characters from the same time period and the same planet to meet)
[localhost:21000] > create table heroes (name string, era string, planet string);
[localhost:21000] > create table villains (name string, era string, planet string);
[localhost:21000] > insert into heroes values
(‘Tesla’,’20th century’,’Earth’),
(‘Pythagoras’,’Antiquity’,’Earth’),
(‘Zopzar’,’Far Future’,’Mars’);
Inserted 3 rows in 2.28s
[localhost:21000] > insert into villains values
(‘Caligula’,’Antiquity’,’Earth’),
(‘John Dillinger’,’20th century’,’Earth’),
(‘Xibulor’,’Far Future’,’Venus’);
Inserted 3 rows in 1.93s
[localhost:21000] > select concat(heroes.name,’ vs. ‘,villains.name) as battle
from heroes join villains
where heroes.era = villains.era and heroes.planet = villains.planet;
+————————–+
| battle |
+————————–+
| Tesla vs. John Dillinger |
| Pythagoras vs. Caligula |
+————————–+
Returned 2 row(s) in 0.47s
读者要求采取进一步行动,所以我们增加了时间旅行和空间旅行的元素,这样英雄可能遇上任何坏蛋(Readers demanded more action, so we added elements of time travel and space travel so that any hero could face any villain)。在 Impala 1.2.2 之前,这一行动是不可能的,因为所有连接都要求两个表有相同的值(this type of query was impossible because all joins had to reference matching values between the two tables):
[localhost:21000] > – Cartesian product not possible in Impala 1.1.
select concat(heroes.name,’ vs. ‘,villains.name) as battle from heroes join villains;
ERROR: NotImplementedException: Join between ‘heroes’ and ‘villains’ requires at least one conjunctive equality predicate between the two tables
在 Impala 1.2.2 中,我们略我修改了查询,使用交叉连接(CROSS JOIN)而不是JOIN,现在结果包含了所有的可能组合:
[localhost:21000] > – Cartesian product available in Impala 1.2.2 with the CROSS JOIN syntax.
select concat(heroes.name,’ vs. ‘,villains.name) as battle from heroes cross join villains;
+——————————-+
| battle |
+——————————-+
| Tesla vs. Caligula |
| Tesla vs. John Dillinger |
| Tesla vs. Xibulor |
| Pythagoras vs. Caligula |
| Pythagoras vs. John Dillinger |
| Pythagoras vs. Xibulor |
| Zopzar vs. Caligula |
| Zopzar vs. John Dillinger |
| Zopzar vs. Xibulor |
+——————————-+
Returned 9 row(s) in 0.33s
两个表中列的所有组合被称为笛卡尔积。这一类型的结果集通常用于创建网格数据结构(grid data structures)。你仍然可以在 WHERE 子句中使用没有在两个表之间明确比较的列来筛选行(You can also filter the result set by including WHEREclauses that do not explicitly compare columns between the two tables)。下面的例子展示了为图表产生一个年度和季度的组合,然后一个短的只有选中季度的列表(The following example shows how you might produce a list of combinations of year and quarter for use in a chart, and then a shorter list with only selected quarters)。
[localhost:21000] > create table x_axis (x int);
[localhost:21000] > create table y_axis (y int);
[localhost:21000] > insert into x_axis values (1),(2),(3),(4);
Inserted 4 rows in 2.14s
[localhost:21000] > insert into y_axis values (2010),(2011),(2012),(2013),(2014);
Inserted 5 rows in 1.32s
[localhost:21000] > select y as year, x as quarter from x_axis cross join y_axis;
+——+———+
| year | quarter |
+——+———+
| 2010 | 1 |
| 2011 | 1 |
| 2012 | 1 |
| 2013 | 1 |
| 2014 | 1 |
| 2010 | 2 |
| 2011 | 2 |
| 2012 | 2 |
| 2013 | 2 |
| 2014 | 2 |
| 2010 | 3 |
| 2011 | 3 |
| 2012 | 3 |
| 2013 | 3 |
| 2014 | 3 |
| 2010 | 4 |
| 2011 | 4 |
| 2012 | 4 |
| 2013 | 4 |
| 2014 | 4 |
+——+———+
Returned 20 row(s) in 0.38s
[localhost:21000] > select y as year, x as quarter from x_axis cross join y_axis where x in (1,3);
+——+———+
| year | quarter |
+——+———+
| 2010 | 1 |
| 2011 | 1 |
| 2012 | 1 |
| 2013 | 1 |
| 2014 | 1 |
| 2010 | 3 |
| 2011 | 3 |
| 2012 | 3 |
| 2013 | 3 |
| 2014 | 3 |
+——+———+
Returned 10 row(s) in 0.39s
使用 impala-shell 连接到 Impala
本教程中演示了许多使用 impala-shell 连接 Impala的技巧,并提供了特定场景的使用技巧。
impala-shell 不使用参数启动会默认连接本机的21000端口
-i 主机 选项快速连接某台主机(-i localhost option gives you a shorter command prompt)
CONNECT hostname 可以切换到其他主机 (使用默认的 21000 端口)
可以从一个完全不同的主机运行 impala-shell 登录到实际的 Impala 节点
为了负载均衡,并发查询应连接不同的协调器节点
为了性能,应当跳过完全显示甚至一点都不输出到屏幕上(For benchmarking, you would skip pretty printing or even output to screen at all)