Impala基礎語法(二)
Impala SQL 語言元素(Elements)
Impala SQL 方言支援一組標準元素(a range of standard elements),加上許多大資料方面的擴充套件,用於資料載入和資料倉庫方面。
注意:
在之前的 Impala beta 版中,在 impala-shell 中每一語句結束時的分號是可選的。現在 impala-shell 支援多行命令,以便於從指令碼檔案中複製貼上程式碼,這樣每一語句結束時的分號是必需的。
下面章節演示了 Impala 中 SQL 語言的主要語句、子句以及其他元素。
繼續閱讀:
ALTER TABLE 語句
ALTER TABLE 語句用來修改現有表的結構或屬性。在 Impala 裡,這是一個邏輯操作,更新了 Impala 和 Hive 共用的 metastore 資料庫中表的元資料; ALTER TABLE 語句不會對實際的資料檔案進行重寫、移動等操作。因此,你可能需要相應的物理檔案系統操作才能實現移動資料檔案到不同的 HDFS 目錄,重寫資料檔案來包含其他欄位,或轉換成不同的檔案格式。
重命名錶:
ALTER TABLE old_name RENAME TO new_name;
對於內部表,這一操作實際地修改了包含資料檔案的 HDFS 目錄名;原始目錄將不再存在。通過修改表名前面的資料庫名,你可以把一個數據庫中的內部表(包括對應的資料目錄)移動到另一個數據庫。例如:
create database d1;
create database d2;
create database d3;
use d1;
create table mobile (x int);
use d2;
-- 移動其他資料庫中的表到當前資料庫
alter table d1.mobile rename to mobile;
use d1;
-- 移動一個數據庫中的表達哦另一個數據庫
alter table d2.mobile rename to d3.mobile;
修改 Impala 查詢表的相關資料檔案的物理位置:
ALTER TABLE table_name SET LOCATION 'hdfs_path_of_directory';
指定的路徑是資料檔案所在的完整路徑,或者是不存在被建立的路徑。Impala 不會建立該表名下面的額外子目錄。Impala 不會移動任意資料檔案到新位置,也不會修改這一目錄下現存的資料檔案。
修改 TBLPROPERTIES 和 SERDEPROPERTIES 列的鍵值對:
ALTER TABLE table_name SET TBLPROPERTIES ('key1'='value1', 'key2'='value2', ...);
ALTER TABLE table_name SET SERDEPROPERTIES ('key1'='value1', 'key2'='value2', ...);
TBLPROPERTIES 子句是將任意使用者指定資料項與特定表關聯起來的主要方法(The TBLPROPERTIES clause is primarily a way to associate arbitrary user-specified data items with a particular table)。SERDEPROPERTIES 子句設定表如何讀寫,在 Hive 中許多情況下需要,實際在 Impala 中未使用(The SERDEPROPERTIES clause sets up metadata defining how tables are read or written, needed in some cases by Hive but not actually used by Impala)。參考 CREATE TABLE Statement 瞭解這些子句的詳細資訊。參考 Setting Statistics Manually through ALTER TABLE 中的使用表屬性來微調相關表統計資訊的效能的例子(for an example of using table properties to fine-tune the performance-related table statistics)。
重組表中的列:
ALTER TABLE table_name ADD COLUMNS (column_defs);
ALTER TABLE table_name REPLACE COLUMNS (column_defs);
ALTER TABLE table_name CHANGE column_name new_name new_spec;
ALTER TABLE table_name DROP column_name;
其中 column_spec 與 CREATE TABLE 語句中相同:列名,列資料型別,以及可選的列備註。你可以一次新增多個列。無論是新增單個列還是多個列,都需要用括號括起來。當替換列時,原有列的定義都被廢棄。你可能會在收到一組新的有不同資料型別或不同順序的列的資料檔案時使用這一技術(資料檔案會被保留,因此當新列與舊列不相容時,需要在執行進一步的查詢前,使用 INSERT OVERWRITE 或 LOAD DATA OVERWRITE 語句替換所有的資料)。
你可以使用 CHANGE 子句重新命名某一個列,或轉換現存的列為其他型別,例如在 STRING 和 TIMESTAMP 之間轉換,或者在 INT 與 BIGINT 之間轉換。一次只能刪除一個列;想要刪除多個列,需要執行多次 ALTER TABLE 語句,或者在單個 ALTER TABLE ... REPLACE COLUMNS 語句中定義一組新的列。
修改 Impala 中表期望的檔案格式(To change the file format that Impala expects table data to be in):
ALTER TABLE table_name SET FILEFORMAT { PARQUET | PARQUETFILE | TEXTFILE | RCFILE | SEQUENCEFILE }
因為本操作只是修改表的元資料,對現存的資料,你必須使用 Impala 之外的 Hadoop 技術對已有的資料進行轉換。之後再在 Impala 中使用 INSERT 語句建立的資料將使用新的格式。你不能指定文字檔案的分隔符;文字檔案的分隔符必須是逗號。
為了新增或刪除表的分割槽, 表必須已經是分割槽表(也就是說,使用帶 PARTITIONED BY 子句建立的表)。分割槽是一個 HDFS 中的實際目錄,目錄名包含特定列的值(partition key,分割槽鍵)。假如必要,Impala 的 INSERT 語句會建立分割槽,因此 ALTER TABLE ... ADD PARTITION 語句的主要用途是通過移動或複製已有的資料檔案到分割槽對應的 HDFS 目錄來匯入資料。DROP PARTITION 子句用於刪除一組指定分割槽鍵值對應的 HDFS 目錄和對應的資料檔案;例如,假如你總是分析最近 3 個月資料的價值,在每個月初你就可以刪除掉不再需要的最老的那個分割槽的資料。刪除分割槽會減少表相關的元資料數量,減輕計算查詢計劃的複雜度,從而可以簡化和提升分割槽表的查詢速度,特別是連線查詢。下面展示了 ADD PARTITION 和 DROP PARTITION 子句。
-- 建立一個空的分割槽模式的表
create table part_t (x int) partitioned by (month string);
-- 建立一個空分割槽,下面將從其他源複製資料檔案到這個分割槽
alter table part_t add partition (month='January');
-- 變更相關資料後,執行 REFRESH 語句使得資料對 Impala 可見
refresh part_t;
-- 然後,新增下一月份
alter table part_t add partition (month='February');
-- 現在不再需要一月份資料
alter table part_t drop partition (month='January');
-- 假如表是根據月份、年份分割槽,執行類似語句:
-- alter table part_t drop partition (year=2003,month='January');
-- 這將需要 12 個 ALTER TABLE 語句來刪除 2003 整年的資料
分割槽鍵的值可以是任意常數表示式,不需要引用標中的列(The value specified for a partition key can be an arbitrary constant expression, without any references to columns).例如:
alter table time_data add partition (month=concat('Decem','ber'));
alter table sales_data add partition (zipcode = cast(9021 * 10 as string));
使用注意:
在 ALTER TABLE 語句中,必須包括所有的分割槽列(Whenever you specify partitions in an ALTER TABLE statement, you must include all the partitioning columns in the specification)。
對於內部表(Impala 管理表)和外部表(資料檔案在任意位置)來說,之前的絕大多數操作是一致的。唯一的列外是重命名錶;對外部表來說,相關的資料目錄不會被重新命名或移動。
假如為了負載均衡的原因,在 impala-shell 會話中連線到了不同的 Impala 節點,可以啟用 SYNC_DDL 查詢選項以使得每一 DDL 語句在新的或修改的元資料被所有 Impala 節點接受前等待,直到都被接受後才返回。參考 SYNC_DDL 瞭解詳細資訊。
注意:
重組表和其關聯的資料檔案的另一種方法是使用 CREATE TABLE 語句建立一個與原始表不同的表,然後使用 INSERT 語句複製轉換或重新排序的資料到新表。ALTER TABLE 的優勢是避免了資料檔案的重複複製,允許你使用熟悉的 Hadoop 技術以一種節省空間的方式來重組巨大容量的資料。
語句型別: DDL
ALTER VIEW 語句
修改視圖裡的查詢,或相關的資料庫和/或檢視的名稱。
因為檢視是一種純邏輯結構(一個查詢的別名)沒有實際的資料,ALTER VIEW 只執行 metastore 資料庫中元資料的修改,不涉及 HDFS 中的任意資料檔案。
ALTER VIEW [database_name.]view_name AS select_statement
ALTER VIEW [database_name.]view_name RENAME TO [database_name.]view_name
假如為了負載均衡的原因,在 impala-shell 會話中連線到了不同的 Impala 節點,可以啟用 SYNC_DDL 查詢選項以使得每一 DDL 語句在新的或修改的元資料被所有 Impala 節點接受前等待,直到都被接受後才返回。參考 SYNC_DDL 瞭解詳細資訊。
例子:
create table t1 (x int, y int, s string);
create table t2 like t1;
create view v1 as select * from t1;
alter view v1 as select * from t2;
alter view v1 as select x, upper(s) s from t2;
執行 DESCRIBE FORMATTED 語句來檢視檢視的定義,這將顯示原始 CREATE VIEW 中的查詢:
[localhost:21000] > create view v1 as select * from t1;
[localhost:21000] > describe formatted v1;
Query finished, fetching results ...
+------------------------------+------------------------------+----------------------+
| name | type | comment |
+------------------------------+------------------------------+----------------------+
| # col_name | data_type | comment |
| | NULL | NULL |
| x | int | None |
| y | int | None |
| s | string | None |
| | NULL | NULL |
| # Detailed Table Information | NULL | NULL |
| Database: | views | NULL |
| Owner: | cloudera | NULL |
| CreateTime: | Mon Jul 08 15:56:27 EDT 2013 | NULL |
| LastAccessTime: | UNKNOWN | NULL |
| Protect Mode: | None | NULL |
| Retention: | 0 | NULL |
| Table Type: | VIRTUAL_VIEW | NULL |
| Table Parameters: | NULL | NULL |
| | transient_lastDdlTime | 1373313387 |
| | NULL | NULL |
| # Storage Information | NULL | NULL |
| SerDe Library: | null | NULL |
| InputFormat: | null | NULL |
| OutputFormat: | null | NULL |
| Compressed: | No | NULL |
| Num Buckets: | 0 | NULL |
| Bucket Columns: | [] | NULL |
| Sort Columns: | [] | NULL |
| | NULL | NULL |
| # View Information | NULL | NULL |
| View Original Text: | SELECT * FROM t1 | NULL |
| View Expanded Text: | SELECT * FROM t1 | NULL |
+------------------------------+------------------------------+----------------------+
Returned 29 row(s) in 0.05s
語句型別: DDL
AVG 函式
返回一組數字的均值的聚合函式。它唯一的引數是一個數值列、或者基於列返回數值的函式或表示式(Its single argument can be numeric column, or the numeric result of a function or expression applied to the column value)。指定列中值為 NULL 的行將被忽略。假如表為空,或者輸入 AVG 的值都是 NULL,則 AVG 返回 NULL。
當查詢包含 GROUP BY 子句,返回每一個分組組合的一個值。
返回型別: DOUBLE
例子:
-- 計算所有非空行的均值
insert overwrite avg_t values (2),(4),(6),(null),(null);
-- 上面表中的均值是 4: (2+4+6) / 3. 兩個 NULL 值被忽略
select avg(x) from avg_t;
-- 計算特定行的均值(Average only certain values from the column)
select avg(x) from t1 where month = 'January' and year = '2013';
-- 在計算均值前進行計算
select avg(x/3) from t1;
-- 在計算均值前對列進行函式運算
-- 這裡把所有 NULL 的行替換為 0
-- 這樣值為 NULL 的行也會作為均值計算的因子
select avg(isnull(x,0)) from t1;
-- 對 string 列使用某些返回值為數字的函式,然後計算均值
-- 假如某行 s 的值包含 NULL,則 length(s) 函式也返回 NULL,該行被忽略
select avg(length(s)) from t1;
-- 也可以與 DISTINCT 和/或 GROUP BY 組合使用
-- 返回多於一個的結果
select month, year, avg(page_visits) from web_stats group by month, year;
-- 在執行計算前過濾重複的值
select avg(distinct x) from t1;
-- 執行計算後過濾輸出的值
select avg(x) from t1 group by y having avg(x) between 1 and 20;
BETWEEN 操作符
在 WHERE 子句中,將表示式與下限和上限比較。當表示式大於等於下限,並且小於等於上限,則表示式比較成功。假如上限下限互換,也就是說下限大於上限,那麼就不匹配任何值。
語法: expression BETWEEN lower_bound AND upper_bound
資料型別: 通常使用數字型別。適用於任何型別但不是很實用的 BOOLEAN(Works with any data type, although not very practical for BOOLEAN values)。 (BETWEEN false AND true 會匹配所有的 BOOLEAN 值)。必要時使用 CAST() 函式來確保下限和上限值是相容的資料型別。假如必要的時候呼叫 string 或 date/time 函式來提取或轉換相關的比較部分,特別是值可以轉換成數字的時候。
使用注意:使用短字串運算元時要當心(Be careful when using short string operands)。以上限的字串開始的長字串將不被包含,因為它被認為是大於上限(A longer string that starts with the upper bound value will not be included, because it is considered greater than the upper bound)。例如,BETWEEN 'A' and 'M' 將不會匹配字串 'Midway'。假如必要,使用例如 upper(), lower(), substr(), trim(), 等等函式以確保比較如預期執行。
例子:
-- 返回1到6月的值,包括1跟6月.
select c1 from t1 where month between 1 and 6;
-- 返回以'A' 到 'M' 開頭的名字
-- 只檢測第一個字元以確保所有以 'M' 開頭的名稱符合
-- 進行大小寫敏感的比較以配合不同大小寫約定的名稱(Do a case-insensitive comparison to match names with various capitalization conventions)
select last_name from customers where upper(substr(last_name,1,1)) between 'A' and 'M';
-- 返回每個月第一週的資料
select count(distinct visitor_id)) from web_traffic where dayofmonth(when_viewed) between 1 and 7;
BIGINT 資料型別
8位元組的整數型別,用於 CREATE TABLE 和 ALTER TABLE 語句。
範圍: -9223372036854775808 .. 9223372036854775807。沒有無符號子型別。
轉換: Impala 自動轉換為浮點型別(FLOAT or DOUBLE)。 使用 CAST() 函式轉換成 TINYINT, SMALLINT, INT, STRING, or TIMESTAMP。數值 N 轉換成 TIMESTAMP 時,是轉換成從 1970年1月1日開始的 N 秒。
BOOLEAN 資料型別
用於 CREATE TABLE 和 ALTER TABLE 語句的資料型別,表示一個單一的 true/false 的選擇。
範圍: TRUE or FALSE。不要使用引號引起 TRUE 和 FALSE 的字元值。你可以使用大寫、小寫或混合格式的值。表中返回的值都是小寫的 true 或 false。
轉換: Impala 不會自動轉換其他型別為 BOOLEAN。可以使用 CAST() 轉換任意 integer 或 float-point 型別為 BOOLEAN: 0 表示 false,其他非零值轉化為 true。STRING 不能轉換為 BOOLEAN,儘管 BOOLEAN 可以轉換為 STRING,其中 true 對應 '1' 而 false 對應 '0'。
註釋
Impala 支援大家熟悉的 SQL 註釋風格:
- 從 -- 開始的到行尾都被作為註釋而忽略。這種型別的註釋可以單獨出現在一行上,或者所有或部分語句之後
- 從 /* 開始到下一個 */ 結束的文字都被作為註釋而忽略。這種型別的註釋可以跨越多行。這種型別的註釋可以在語句中或者語句之前、之後出現在一行或多行
例如:
-- 本行是表的註釋
create table ...;
/*
本還是查詢的多行註釋
*/
select ...;
select * from t /* 這是查詢的嵌入式註釋 */ where ...;
select * from t -- 這是多行命令中的尾部註釋
where ...;
比較操作
Impala 支援大家熟悉的比較操作用於檢測相等、存在併為列資料型別排序:
- =, !=, <>
- IS NULL, IS NOT NULL
- <, <=, >, >=
- BETWEEN lower_bound AND upper_bound
- LIKE, REGEXP (僅支援STRING)
COMPUTE STATS 語句
採集關於表和相關列與分割槽中資料的資料量和分佈(Gathers information about volume and distribution of data in a table and all associated columns and partitions)。這些資訊被存放在 metastore 資料庫中,被 Impala 用於幫助優化查詢。假設 Impala 可以判斷表的大小,有許多或幾個的不同的值,那麼它可以為連線查詢或插入操作組織適當的並行操作。瞭解這一語句採集的幾種資訊,參見 Table Statistics。
使用注意:
原來 Impala 依靠使用者執行 Hive ANALYZE TABLE 語句,但這一方法採集的統計資訊被證明是緩慢和不可靠的。Impala 的 COMPUTE STATS 語句是從底層向上構建,以提高可用性和使用者友好度。你可以執行一個單獨的 Impala COMPUTE STATS 語句來採集包括 table 和 column 的統計資訊,而不是為表和列的統計資訊分別執行 Hive ANALYZE TABLE 語句。
COMPUTE STATS 也可以採集 HBase 表的資訊。採集的 HBase 表的統計資訊與 HDFS-backed 表的有所不同,但當 HBase 表執行連線查詢時,統計資訊仍被用於優化。
例子:
本例中展示了 T1 和 T2 兩個表,其中 T1.ID 和 T2.PARENT 存在父子關係,有少量的不同的值連結。T1 是小表,而 T2 大概有 100K 行。最初,統計資訊包括物理度量如檔案的數量,總大小,以及定長列如 INT 型別的大小度量。未知值表示為 -1。為每個表執行 COMPUTE STATS 之後,SHOW STATS 語句中有更多資訊可用。假如你執行一個涉及這兩個表的連線查詢,你需要統計這兩個表以獲得最優化的查詢。
[localhost:21000] > show table stats t1;
Query: show table stats t1
+-------+--------+------+--------+
| #Rows | #Files | Size | Format |
+-------+--------+------+--------+
| -1 | 1 | 33B | TEXT |
+-------+--------+------+--------+
Returned 1 row(s) in 0.02s
[localhost:21000] > show table stats t2;
Query: show table stats t2
+-------+--------+----------+--------+
| #Rows | #Files | Size | Format |
+-------+--------+----------+--------+
| -1 | 28 | 960.00KB | TEXT |
+-------+--------+----------+--------+
Returned 1 row(s) in 0.01s
[localhost:21000] > show column stats t1;
Query: show column stats t1
+--------+--------+------------------+--------+----------+----------+
| Column | Type | #Distinct Values | #Nulls | Max Size | Avg Size |
+--------+--------+------------------+--------+----------+----------+
| id | INT | -1 | -1 | 4 | 4 |
| s | STRING | -1 | -1 | -1 | -1 |
+--------+--------+------------------+--------+----------+----------+
Returned 2 row(s) in 1.71s
[localhost:21000] > show column stats t2;
Query: show column stats t2
+--------+--------+------------------+--------+----------+----------+
| Column | Type | #Distinct Values | #Nulls | Max Size | Avg Size |
+--------+--------+------------------+--------+----------+----------+
| parent | INT | -1 | -1 | 4 | 4 |
| s | STRING | -1 | -1 | -1 | -1 |
+--------+--------+------------------+--------+----------+----------+
Returned 2 row(s) in 0.01s
[localhost:21000] > compute stats t1;
Query: compute stats t1
+-----------------------------------------+
| summary |
+-----------------------------------------+
| Updated 1 partition(s) and 2 column(s). |
+-----------------------------------------+
Returned 1 row(s) in 5.30s
[localhost:21000] > show table stats t1;
Query: show table stats t1
+-------+--------+------+--------+
| #Rows | #Files | Size | Format |
+-------+--------+------+--------+
| 3 | 1 | 33B | TEXT |
+-------+--------+------+--------+
Returned 1 row(s) in 0.01s
[localhost:21000] > show column stats t1;
Query: show column stats t1
+--------+--------+------------------+--------+----------+----------+
| Column | Type | #Distinct Values | #Nulls | Max Size | Avg Size |
+--------+--------+------------------+--------+----------+----------+
| id | INT | 3 | 0 | 4 | 4 |
| s | STRING | 3 | 0 | -1 | -1 |
+--------+--------+------------------+--------+----------+----------+
Returned 2 row(s) in 0.02s
[localhost:21000] > compute stats t2;
Query: compute stats t2
+-----------------------------------------+
| summary |
+-----------------------------------------+
| Updated 1 partition(s) and 2 column(s). |
+-----------------------------------------+
Returned 1 row(s) in 5.70s
[localhost:21000] > show table stats t2;
Query: show table stats t2
+-------+--------+----------+--------+
| #Rows | #Files | Size | Format |
+-------+--------+----------+--------+
| 98304 | 1 | 960.00KB | TEXT |
+-------+--------+----------+--------+
Returned 1 row(s) in 0.03s
[localhost:21000] > show column stats t2;
Query: show column stats t2
+--------+--------+------------------+--------+----------+----------+
| Column | Type | #Distinct Values | #Nulls | Max Size | Avg Size |
+--------+--------+------------------+--------+----------+----------+
| parent | INT | 3 | 0 | 4 | 4 |
| s | STRING | 6 | 0 | -1 | -1 |
+--------+--------+------------------+--------+----------+----------+
Returned 2 row(s) in 0.01s
COUNT 函式
返回滿足一定條件記錄的行數或非空行的行數的聚合函式:
- COUNT(*) 統計包含 NULL 值的所有行數
- COUNT(column_name) 只計算該列中值非空的行數
- 可以結合使用 COUNT 與 DISTINCT 在計算前消除重複值,並計算多個列組合的值
當查詢中包含 GROUP BY 子句時,we
Return type: BIGINT
Examples:
-- 表中有多少行,不關心是否有 NULL 值
select count(*) from t1;
-- 表中有多少 c1 列的值不為空的行
select count(c1) from t1;
-- 計算滿足條件的行數
-- 另外, * 包括 NULL, 因此 COUNT(*) 可能比 COUNT(col) 的值大.
select count(*) from t1 where x > 10;
select count(c1) from t1 where x > 10;
-- 可以與 DISTINCT 和/或 GROUP BY 操作聯合使用
-- 聯合使用 COUNT 和 DISTINCT 查詢唯一值的個數
-- 在 COUNT(DISTINCT ...) 語法中必須使用列名而不是 *
-- c1 包含空值的行不會統計
select count(distinct c1) from t1;
-- c1 或 c2 中包含空值的每一行都不會統計(Rows with a NULL value in _either_ column are not counted)
select count(distinct c1, c2) from t1;
-- 返回多個結果
select month, year, count(distinct visitor_id) from web_stats group by month, year;
CREATE DATABASE 語句
在 Impala 裡,資料庫是:
- 邏輯結構,包含在自己名稱空間下組合在一起的相關的表(A logical construct for grouping together related tables within their own namespace)。你可以每個應用、一組相關的表或一輪實驗都使用單獨的資料庫(You might use a separate database for each application, set of related tables, or round of experimentation)
- 物理結構,對應 HDFS 中的目錄樹(A physical construct represented by a directory tree in HDFS)。表(內部表),分割槽,和資料檔案都在該目錄下分配。你可以備份、計算空間使用情況、或使用 DROP DATABASE 語句刪除它(目錄為空時)
建立資料的語法如下:
CREATE (DATABASE|SCHEMA) [IF NOT EXISTS]database_name[COMMENT 'database_comment']
[LOCATION hdfs_path];
資料庫實際對應 HDFS 中 Impala 資料目錄中的目錄,目錄名為資料庫名+.db。假如 HDFS 中相關目錄不存在則自動建立。所有資料庫和它們相關的目錄是頂層物件,沒有邏輯或物理巢狀(All databases and their associated directories are top-level objects, with no physical or logical nesting)。
使用注意:
當建立資料庫之後,在 impala-shell 會話中,使用 USE 語句切換為當前資料庫。你可以不加資料庫名字首訪問當前資料庫中的表。
當第一次使用 impala-shell 連線到 Impala,預設的開始資料庫是 (在執行任意的 CREATE DATABASE 或 USE 語句前) default。
當建立資料庫之後,你的 impala-shell 會話或其他的連線到相同節點的 impala-shell 會話可以立即訪問該資料庫。當通過其他節點的 Impala 守護程序訪問該資料庫時,應先執行 INVALIDATE METADATA 語句
假如為了負載均衡的原因,在 impala-shell 會話中連線到了不同的 Impala 節點,可以啟用 SYNC_DDL 查詢選項以使得每一 DDL 語句在新的或修改的元資料被所有 Impala 節點接受前等待,直到都被接受後才返回。參考 SYNC_DDL 瞭解詳細資訊。
例子:
create database first;
use first;
create table t1 (x int);
create database second;
use second;
-- 資料庫中的表以資料庫名作為它的名稱空間
-- 不同的資料庫中可以有同名的表
create table t1 (s string);
create database temp;
-- 建立資料庫後沒有使用 USE 語句切換資料庫,而是通過資料庫名字首來標識表
create table temp.t2 (x int, y int);
use database temp;
create table t3 (s string);
-- 當資料庫被 USE 語句選中時,無法刪除
drop database temp; ERROR: AnalysisException: Cannot drop current default database: temp -- The always-available database 'default' is a convenient one to USE.
use default;
-- 刪除資料庫可以快速刪除下面的所有表
drop database temp;
語句型別: DDL
CREATE FUNCTION 語句
建立一個使用者定義函式(UDF),當執行 SELECT 或 INSERT 操作時,可以實現自定義的邏輯。
語法:
建立標量函式(scalar UDF)與聚合函式(UDA)的語法不同。標量函式每行呼叫一次,執行單個函式(which is called once for each row and implemented by a single function),而使用者定義聚合函式執行多個函式跨越多組行的中間結果(which is implemented by multiple functions that compute intermediate results across sets of rows)。
執行 CREATE FUNCTION 語句建立標量函式:
CREATE FUNCTION [IF NOT EXISTS] [db_name.]function_name([arg_type[,arg_type...])
RETURNS return_type LOCATION 'hdfs_path'
SYMBOL='symbol_or_class'
執行 CREATE AGGREGATE FUNCTION 語句建立 UDA:
CREATE [AGGREGATE] FUNCTION [IF NOT EXISTS] [db_name.]function_name([arg_type[,arg_type...])
RETURNSreturn_typeLOCATION 'hdfs_path'
[INIT_FN='function]
UPDATE_FN='function MERGE_FN='function [FINALIZE_FN='function]
標量與聚合函式:
最簡單的一種使用者定義函式每次呼叫時返回一個標量值,典型的是結果集中每一行返回一個值。這種普通的函式通常稱為 UDF。使用者定義聚合函式(UDA) 是一種特別的基於多行的內容產生單一值的 UDF。通常 UDA 會與 GROUP BY子句聯合使用,壓縮大的結果集到一個小的結果集,甚至對整表產生一個概述列(This general kind of function is what is usually meant by UDF. User-defined aggregate functions (UDAs) are a specialized kind of UDF that produce a single value based on the contents of multiple rows. You usually use UDAs in combination with a GROUP BY clause to condense a large result set into a smaller one, or even a single row summarizing column values across an entire table)。
使用 CREATE AGGREGATE FUNCTION 語句建立 UDA。 僅當建立 UDA 而不是 標量 UDF 時,INIT_FN, UPDATE_FN, MERGE_FN, FINALIZE_FN, INTERMEDIATE 子句被使用。
使用 *_FN 子句指定的函式在函式處理的不同階段進行呼叫。
- Initialize: 在 INIT_FN 子句中指定的函式完成初始化設定,例如初始化內部資料結果的成員變數。This function is often a stub for simple UDAs. 你可以忽略這一子句則會執行一個預設(無操作)函式操作。
- Update: 在 UPDATE_FN 子句中指定的函式會在原始結果集的每一行呼叫一次,也就是說,在執行 GROUP BY 子句之前被執行。 對於 GROUP BY 子句返回的每一個不同的值,會呼叫一個單獨的函式例項(A separate instance of the function is called for each different value returned by the GROUP BY clause)。 The final argument passed to this function is a pointer, to which you write an updated value based on its original value and the value of the first argument.
- Merge: 在 MERGE_FN 子句中指定的函式被呼叫任意次數,與不同節點或不同執行緒的 Impala 並行讀取和處理資料檔案產生的中間結果有關。The final argument passed to this function is a pointer, to which you write an updated value based on its original value and the value of the first argument.
- Finalize: 在 FINALIZE_FN 子句執行釋放之前的 UDF 申請的資源,例如釋放記憶體,關閉之前開啟的檔案控制代碼,諸如此類。This function is often a stub for simple UDAs. 你可以忽略這一子句則會執行一個預設(無操作)函式操作。
假如你對每一個相關的函式使用一致的命名約定,Impala 基於最初的子句可以自動的確定函式名稱,因此其餘的是可選的(If you use a consistent naming convention for each of the underlying functions, Impala can automatically determine the names based on the first such clause, so the others are optional)。
使用注意:
- 你可以使用 C++ 或 JAVA 編寫 Impala UDF。對於 Impala 來說,C++ UDFs 是新的、推薦的格式,可以利用原生代碼提供更高效能。Impala 和 Hive 都相容基於 JAVA(Java-based) 的 UDFs,最適合重用現存的 Hive UDFs (Impala 可以執行基於 Java 的 Hive UDFs 但不支援 Hive UDAs)
- UDF 對應一個 .so 或 .jar 檔案,存放在 HDFS 中,並由 CREATE FUNCTION 語句分發到每一個 Impala 節點
- 當 SQL 語句執行時,Impala 根據處理結果集中所有行的需要呼叫相關的程式碼。所有的 UDF 被分為是確定的,也就是說,當傳入相同的引數值時總是返回相同的結果。當從之前的呼叫中結果值已知,Impala 可能跳過也可能不跳過 UDF 的某些呼叫。因此,不要依賴於 UDF 特定的呼叫次數,也不要基於一些外部因素如當前時間、隨機數函式或當 Impala 執行查詢過程中值會發生變化的外部資料來源而返回不同的結果(Impala calls the underlying code during SQL statement evaluation, as many times as needed to process all the rows from the result set. All UDFs are assumed to be deterministic, that is, to always return the same result when passed the same argument values. Impala might or might not skip some invocations of a UDF if the result value is already known from a previous call. Therefore, do not rely on the UDF being called a specific number of times, and do not return different result values based on some external factor such as the current time, a random number function, or an external data source that could be updated while an Impala query is in progress)
- UDF 函式中的引數名不重要,重要的是它們的數量、位置和資料型別
- 你可以通過建立多版本的使用不同引數簽名的函式來過載相同的函式名,但基於安全的原因,不允許建立與內部函式重名的 UDF 函式
- 在 UDF 程式碼裡,函式返回一個 struct。其中 struct 包含兩個欄位.。第一個欄位是 boolean 型別,表示返回值是否為 NULL(當本欄位返回 true 時,返回值被解釋為 NULL)。第二個欄位與函式的返回型別資料型別相同,當函式返回值不為 NULL 時持有返回值
- In the UDF code, you represent the function arguments as an initial pointer to a UDF context structure, followed by references to zero or more structs, corresponding to each of the arguments. Each struct has the same 2 fields as with the return value, a boolean field representing whether the argument is NULL, and a field of the appropriate type holding any non-NULL argument value.
- 關於 UDF 的例子程式碼和編譯說明,參考 Impala 提供的例子目錄
- 因為 對於 UDF 函式主體的檔案存放在 HDFS中,自動對所有的 Impala 節點可用。你不需要在伺服器之間手工複製 UDF 相關檔案
- 因為 Impala 目前不支援 ALTER FUNCTION 語句,假如你需要重新命名函式,移動到其他資料庫,或者修改它的前面或其他屬性,應先對原函式執行 DROP FUNCTION 語句進行刪除,然後執行以期望的屬性執行 CREATE FUNCTION 語句建立函式
- 因為每一個 UDF 與特定的資料庫相關,因此在執行任何 CREATE FUNCTION 語句之前,應先執行 USE 語句指定資料庫,或者使用 db_name.function_name 來指定資料庫
假如為了負載均衡的原因,在 impala-shell 會話中連線到了不同的 Impala 節點,可以啟用 SYNC_DDL 查詢選項以使得每一 DDL 語句在新的或修改的元資料被所有 Impala 節點接受前等待,直到都被接受後才返回。參考 SYNC_DDL 瞭解詳細資訊。
語句型別: DDL
相容性:
Impala 可以執行 Hive 中建立的 UDF,只要它使用 Impala-compatible 資料型別 (沒有組合或巢狀列型別)。Hive 可以執行 Impala 中建立的基於 JAVA(Java-based)的 UDF,而不能使用 C++編寫的 UDF。
CREATE TABLE 語句
建立表並指定它的列的語法如下:
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name[(col_namedata_type[COMMENT 'col_comment'], ...)]
[COMMENT 'table_comment']
[PARTITIONED BY (col_namedata_type[COMMENT 'col_comment'], ...)]
[
[ROW FORMATrow_format] [STORED ASfile_format]
]
[LOCATION 'hdfs_path']
[WITH SERDEPROPERTIES ('key1'='value1', 'key2'='value2', ...)]
[TBLPROPERTIES ('key1'='value1', 'key2'='value2', ...)]
data_type
:primitive_typeprimitive_type
: TINYINT
| SMALLINT
| INT
| BIGINT
| BOOLEAN
| FLOAT
| DOUBLE
| STRING
| TIMESTAMP
row_format
: DELIMITED [FIELDS TERMINATED BY 'char' [ESCAPED BY 'char']]
[LINES TERMINATED BY 'char']
file_format:
PARQUET | PARQUETFILE
| TEXTFILE
| SEQUENCEFILE
| RCFILE
內部表和外部表:
Impala 預設建立 "內部" 表--由 Impala 管理表相關的資料檔案,當表刪除時同時實際刪除資料檔案。假如使用了 EXTERNAL 子句,Impala 將建立 "外部" 表--通常由 Impala 外部產生資料檔案,並從它們原來的 HDFS 中的位置進行查詢,當刪除表時 Impala 不處理這些資料檔案
分割槽表:
PARTITIONED BY 子句根據一個或多個指定列的值拆分資料檔案。Impala 查詢可以使用分割槽元資料來最小化讀取和網路之間傳遞的資料,特別是連線查詢時。更多資訊參見 Partitioning.
指定檔案格式:
STORED AS 子句標識了相關資料檔案的格式。目前 Impala 可以查詢超出其可以建立與插入資料的檔案格式。對於 Impala 當前不支援的格式,在 Hive 中執行建立或資料載入操作。例如,Impala 可以建立 SequenceFile 表但是無法載入資料。這也是 Impala 處理各種壓縮檔案的特定格式(There are also Impala-specific procedures for using compression with each kind of file format)。關於與不同資料檔案格式協作的詳細資訊,參見 How Impala Works with Hadoop File Formats。
預設(不使用 STORED AS 子句時)的,Impala 中表建立的資料檔案是以 Ctrl-A 作為分隔符的文字檔案。使用 ROW FORMAT 子句指定使用不同的分隔符生成或從檔案提取資料,如 tab 或 |,或指定不同的行結束符,如回車或換行。當指定分隔符和行結束符號時,用 '\t' 表示 tab,'\n' 表示回車, '\r' 表示換行。
ESCAPED BY 子句對通過 INSERT 語句插入到 Impala TEXTFILE 表的資料檔案和已有的直接放置到 Impala 表目錄中的檔案都有效(你可以使用以下方式提取已有檔案的資料:使用 CREATE EXTERNAL TABLE ... LOCATION 語句, 使用 LOAD DATA 語句, 或通過 HDFS 操作如 hdfs dfs -put file hdfs_path)。選擇一種不會在檔案中其他部分使用的字元作為轉義字元,當欄位值中出現分隔符時放在每個分隔符例項之前(Choose an escape character that is not used anywhere else in the file, and put it in front of each instance of the delimiter character that occurs within a field value)。被引號引起的欄位表示 Impala 不需要對包含嵌入的分隔符的進行解析(Surrounding field values with quotation marks does not help Impala to parse fields with embedded delimiter characters);引號標誌它是組成整個列值的一部分。如下想用 \ 作為轉義符,需要在 impala-shell 中使用 ESCAPED BY '\\' 進行指定。
克隆表:
使用以下語句,建立一個與其他表具有相同的列、備註、以及其他屬性的空表。CREATE TABLE ... LIKE 語句包含一組子句集,當前只支援 LOCATION, COMMENT, STORED AS 子句:
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name
LIKE [db_name.]table_name
[COMMENT 'table_comment']
[STORED ASfile_format]
[LOCATION 'hdfs_path']
Note: 希望在一個操作中同時克隆表結構和資料,則使用下面介紹的 CREATE TABLE AS SELECT 語句。
當使用 CREATE TABLE ... LIKE 語句克隆現有表的結構時,新表與原表使用相同的檔案格式,因此假如你想要使用不同的檔案格式時使用 STORED AS 子句指定新的檔案格式。
通常 Impala 不能直接建立 HBase 表,但 Impala 可以使用 CREATE TABLE ... LIKE 語句克隆 HBase 表,保留原始表的檔案格式和元資料。
使用 CREATE TABLE ... LIKE 語句克隆 Avro 表時可能有一些例外情況。例如無法用此技術克隆一個設定了 Avro schema 但是沒有列的 Avro 表。當有疑問時,在 Hive 中測試執行 CREATE TABLE ... LIKE 操作;如果也有問題,那麼他通常在 Impala 中也不會正常。
如果原始表是分割槽表,新表會繼承相同的分割槽鍵列。因為新表初始化為空表,它沒有繼承原始表的實際分割槽。使用插入資料或執行 ALTER TABLE ... ADD PARTITION 語句在新表上建立分割槽。
因為 CREATE TABLE ... LIKE 只是操作了表的元資料而不是表的物理資料,可以在之後執行 INSERT INTO TABLE 語句從原始表複製一些資料到新表,也可以同時轉換為新的檔案格式(對於一些檔案格式,Impala 可以通過 CREATE TABLE ... LIKE 進行建立,但是不能插入這些檔案格式的資料;這時候就必須使用 Hive 載入資料。參考 How Impala Works with Hadoop File Formats 瞭解詳細資訊)。
CREATE TABLE AS SELECT:
CREATE TABLE AS SELECT 語法同時完成建立基於原始表所定義的列的新表,從原始表複製資料到新表,而且不需要單獨執行 INSERT 語句。這一語句如此流行,都有自己的縮寫 "CTAS"。CREATE TABLE AS SELECT 語法如下:
CREATE [EXTERNAL] TABLE [IF NOT EXISTS]db_name.]table_name
[COMMENT 'table_comment']
[STORED ASfile_format]
[LOCATION 'hdfs_path']
AS
select_statement
參考 SELECT Statement 瞭解關於 CTAS 語句中 SELECT 位置的語法資訊。
新建立的表繼承了從原始表中選出的列名,也可以通過在查詢中指定列別名來修改。列和表的註釋都不會從原始表中繼承。
下面例子演示瞭如何克隆原始表所有資料、列和/或行的部分子集,重排列的順序,重新命名列,用表示式構建新列等:
-- 建立新表並複製所有資料
CREATE TABLE clone_of_t1 AS SELECT * FROM t1;
-- 與 CREATE TABLE LIKE 功能相同
CREATE TABLE empty_clone_of_t1 AS SELECT * FROM t1 WHERE 1=0;
-- 複製部分資料
CREATE TABLE subset_of_t1 AS SELECT * FROM t1 WHERE x > 100 AND y LIKE 'A%';
CREATE TABLE summary_of_t1 AS SELECT c1, sum(c2) AS total, avg(c2) AS average FROM t1 GROUP BY c2;
-- 修改檔案格式
CREATE TABLE parquet_version_of_t1 AS SELECT * FROM t1 STORED AS PARQUET;
-- 建立與原始表不同列順序、列名和資料型別的表
CREATE TABLE some_columns_from_t1 AS SELECT c1, c3, c5 FROM t1;
CREATE TABLE reordered_columns_from_t1 AS SELECT c4, c3, c1, c2 FROM t1;
CREATE TABLE synthesized_columns AS SELECT upper(c1) AS all_caps, c2+c3 AS total, "California" AS state FROM t1;
作為 CTAS 操作的一部分,你可以採用任意 Impala 可寫的資料檔案格式(當前支援 TEXTFILE 和 PARQUET).。但不能設定文字檔案表的底層屬性(lower-level properties)如分隔符。儘管可以使用分割槽表作為源表並從中複製資料,但是不能設定新表的分割槽子句。
Visibility and Metadata:
你可以通過 TBLPROPERTIES 子句關聯任意物件到表的元資料。這會產生一組逗號分隔的鍵值對並儲存到 metastore 資料庫中。建立之後可以使用 ALTER TABLE 語句來修改這些屬性。當前 Impala 查詢不使用表屬性欄位裡的這些資料。一些與其他 Hadoop 元件的互動需要設定 TBLPROPERTIES 欄位為特定的值,例如建立 Avro 表或 HBase 表(通常在 Hive 中建立這些特定型別的表,因為這些表需要一些當前 Impala 不支援的額外子句)。
你也可以通過 WITH SERDEPROPERTIES 子句指定鍵值對來關聯表的 SerDes 屬性。Impala 有自己的內建的所支援檔案的序列化和反序列化器,因此不使用這個屬性。為了與 Hive 相容,一些檔案格式的轉換需要特定的屬性值。
執行 DESCRIBE table_name 語句查看錶的列定義和列備註,例如在執行 CREATE TABLE ... LIKE 或 CREATE TABLE ... AS SELECT 語句之前。使用 DESCRIBE FORMATTED table_name 語句來檢視更詳細的資訊,如資料檔案的位置和如 ROW FORMAT 和 STORED AS 等子句的值。要檢視整體表的註釋(而不是單獨列的註釋)也需要使用 DESCRIBE FORMATTED 語句。
當建立了表之後,當前 impala-shell 會話與其他連線到相同節點的 impala-shell 會話可以立刻看到這個表。當連線到其他節點,通過 Impala 守護程序查詢這個表之前,應先執行 INVALIDATE METADATA 語句。
Hive considerations:
Impala 查詢會使用表和列的元資料,如表的行數或列的不同值個數。在 Impala 1.2.2 之前,當建立完表和載入相應的資料後,需要在 Hive 中執行 ANALYZE TABLE 語句來收集這些元資料資訊。在 Impala 1.2.2 及以上版本,Impala 中 COMPUTE STATS 語句可以生成這些統計資訊,不再需要在 Hive 中執行。
Note:
Impala 的 CREATE TABLE 語句不能建立 HBase 表,因為當前不支援 HBase 表所需的 STORED BY 子句。可以在 Hive 中建立表,在 Impala 中查詢。關於 Impala 使用 HBase 表的資訊,參考 Using Impala to Query HBase Tables。
CREATE VIEW 語句
CREATE VIEW 語句為複雜的查詢建立一個簡寫。所基於的查詢可以執行連線、表示式、重排序列、列別名和其他的 SQL 功能,可以是一個難於理解和維護的查詢。
因為檢視是個純粹的邏輯結構(查詢的別名)沒有對應實體的資料,所以 ALTER VIEW 只會修改 metastore 資料庫中的元資料,而不會涉及 HDFS 中的任意資料檔案。
CREATE VIEW view_name[(column_list)]
AS select_statement
CREATE VIEW 語句可用以一下場景:
- 將最長最複雜的 SQL 查詢轉換為一行查詢,你可以在應用中、指令碼中、或 impala-shell 互動式查詢中執行鍼對檢視的簡單的查詢。例如:
- select * from view_name;
- select * from view_name order by c1 desc limit 10;
原始查詢越複雜越難以閱讀,使用檢視的簡單查詢越有效果。
- 隱藏底層表和列,當這些發生變化時減少維護量。這時候,只需要用新的名稱重建檢視,所有查詢檢視而不是底層表的語句就可以不需要修改就正常執行
- 測試優化技術並把優化後的查詢提供給所有應用使用(To experiment with optimization techniques and make the optimized queries available to all applications)。例如.你發現了一個 WHERE 條件,連線順序,連線提示(join hints),等等組合中在一起能獲得最佳效能的一類查詢,你可以建立一個使用這一最佳組合技術的檢視。應用可以對檢視進行相對簡單的查詢,而不是重複著一遍又一遍的繁雜而優化的邏輯。如何之後發現了比原始查詢更好的優化方式,重建這個檢視,所有應用可以立刻從中受益
- 簡化整類的相關查詢,特別是在多個表執行連線,對列進行復雜計算、以及其他語法導致整個查詢難以理解和除錯查詢。例如你可以建立一個檢視,連線幾個表,使用幾個 WHERE 條件過濾資料,並從結果集選擇幾列。應用可以在這個檢視上上執行僅僅是 LIMIT, ORDER BY 等類似簡單子句上不同的查詢。
對於需要一遍遍重複的查詢的複雜子句,例如在查詢項, ORDER BY, GROUP BY 子句,你可以使用 WITH 子句作為建立檢視的替代方案(you can use the WITH clause as an alternative to creating a view)。
假如為了負載均衡的原因,在 impala-shell 會話中連線到了不同的 Impala 節點,可以啟用 SYNC_DDL 查詢選項以使得每一 DDL 語句在新的或修改的元資料被所有 Impala 節點接受前等待,直到都被接受後才返回。參考 SYNC_DDL 瞭解詳細資訊。
例子:
create view v1 as select * from t1;
create view v2 as select c1, c3, c7 from t1;
create view v3 as select c1, cast(c3 as string) c3, concat(c4,c5) c5, trim(c6) c6, "Constant" c8 from t1;
create view v4 as select t1.c1, t2.c2 from t1 join t2 on (t1.id=t2.id);
create view some_db.v5 as select * from some_other_db.t1;
Statement type: DDL
DESCRIBE 語句
DESCRIBE 語句顯示錶的元資料,例如列的名稱和資料型別。語法為:
DESCRIBE [FORMATTED] table
也可以使用簡寫 DESC。
DESCRIBE FORMATTED 顯示更多資訊,顯示格式與 Apache Hive 類似。擴充套件資訊包括底層詳細資訊如表是內部表還是外部表,何時建立,檔案格式,HDFS 中資料檔案位置,物件是表還是檢視,以及(對檢視來說)從檢視定義中獲得的查詢語句。
Note: Compressed 欄位表是否包含壓縮資料的可靠標誌。通常總是 No,因為僅當會話載入資料的時候使用壓縮設定,並不會持久儲存到表的元資料中。
Usage notes:
當 impalad 守護程序重啟後,對某個表的第一次查詢可能會比之後的查詢時間長,因為該查詢執行時會把表的元資料載入到記憶體中。這種對每個表的一次性(one-time)的延遲可能會誤導基準測試的結果或造成不必要的擔憂。可以為每一個要查詢的表執行 DESCRIBE 語句,為 Impala 的元資料快取"熱身"("warm up")。
當處理儲存在 HDFS 中的資料檔案時,有時候瞭解諸如 Impala 表對應的資料檔案的路徑、namenode 的主機名此類的資訊很重要。你可以通過 DESCRIBE FORMATTED 的輸出獲取這些資訊。在諸如 LOAD DATA 和 CREATE TABLE / ALTER TABLE 中的 LOCATION 子句需要指定 HDFS URIs 或路徑。在 Linux 命令如 hadoop 和 hdfs 對 HDFS 中的資料檔案執行復制,重新命名等操作時,也需要知道 HDFS URIs 或路徑。
假如為了負載均衡的原因,在 impala-shell 會話中連線到了不同的 Impala 節點,可以啟用 SYNC_DDL 查詢選項以使得每一 DDL 語句在新的或修改的元資料被所有 Impala 節點接受前等待,直到都被接受後才返回。參考 SYNC_DDL 瞭解詳細資訊。
每個表都包括對應的表統計資訊和列統計資訊。使用 SHOW TABLE STATS table_name 和 SHOW COLUMN STATS table_name 語句來檢視這些分類的資訊。參見 SHOW Statement 瞭解詳細資訊。
Important: 對於效能關鍵( performance-critical)查詢中用到的表,插入或替換資料之後,應執行 COMPUTE STATS 語句以確保所有統計資訊是最新的。 在 Impala 中執行了 INSERT, LOAD DATA, CREATE TABLE AS SELECT 語句之後,或者在 Hive 中載入資料並在 Impala 中執行 REFRESH table_name之後, 應考慮更新表的統計資訊。對於包含大量資料的表、用於連線查詢的表,這一技術特別重要。
例子:
下面的例子演示了對不同