文章目录
- 前言
- 一、相关介绍
- 1. 内部表和外部表
- 1.1 内部表
- 1.2 外部表
- 2. 分区表
- 二、Impala中操作Kudu表的语法
- 1. 创建Kudu外部表
- 2. 创建Kudu内部表
- 2.1 CTAS(CREATE TABLE AS SELECT)
- 2.2 创建范围分区表
- 2.3 创建哈希分区表
- 2.4 同时使用范围分区和哈希分区
- 2.5 非覆盖范围分区
- 2.5.1 查看范围分区
- 2.5.2 添加范围分区
- 2.5.3 删除范围分区
- 3. 增删改
- 3.1 插入操作
- 3.1.1 插入一行或多行
- 3.1.2 批量插入
- 3.2 更新操作
- 3.3 插入或更新操作
- 3.4 删除操作
- 4. 重命名 Impala 映射表
- 5. 重命名内部表的基础 Kudu 表
- 6. 将外部表重新映射到其他 Kudu 表
- 7. 更改 Kudu 主地址
- 8. 将内部管理的表更改为外部
- 9. 使用 Impala 删除 Kudu 表
- 总结
前言
本教程介绍了在Impala中操作Kudu表的语法和相关概念。我们讨论了内部表和外部表的区别,以及分区表的创建方式。您将学习到如何创建Kudu外部表和内部表,并掌握使用范围分区和哈希分区来优化数据存储和查询性能。此外,我们还提供了增删改等常见操作示例,以及重命名、更改主地址等高级操作。
一、相关介绍
1. 内部表和外部表
在使用Impala创建新的Kudu表时,可以将表创建为内部表或外部表。
1.1 内部表
内部表(由Impala创建)由Impala管理,并且可以被Impala删除。使用Impala创建新表时,它通常是一个内部表。当在Impala中创建这样一个表时,相应的Kudu表将被命名。
1.2 外部表
外部表(由Impala创建)不由Impala管理,删除这样一个表不会从它的源位置(这里是Kudu)删除表。相反,它只是消除了impala和kudu之间的映射。这是Kudu提供的语法中用于将现有表映射到Impala的模式。
2. 分区表
根据主键列上的分区模式将表划分为多个tablet。每个tablet由至少一个tablet服务器提供服务。理想情况下,应该将一个表拆分为多个tablet,这些tablet分布在多个tablet服务器上,以最大化并行操作。
Kudu目前没有在创建表后拆分或合并tablet的机制。在实现此特性之前,必须在创建表时为它提供分区模式。在设计表时,请考虑使用允许将表划分为以相似速度增长的tablet的主键。
创建 Kudu 表时,可以选择是否指定分区。如果未指定分区,则表将是一个无分区的表,所有数据将存储在默认的单个分区中。
二、Impala中操作Kudu表的语法
1. 创建Kudu外部表
通过Kudu API或其他集成(如Apache Spark)创建的表在Impala中不会自动可见。要查询它们,必须首先在Impala中创建一个外部表,将Kudu表映射到Impala数据库中。
CREATE EXTERNAL TABLE my_mapping_table
STORED AS KUDU
TBLPROPERTIES ('kudu.table_name' = 'my_kudu_table');
2. 创建Kudu内部表
从Impala在Kudu中创建一个新表类似于将现有Kudu表映射到Impala表,不同之处是您需要自己指定模式和分区信息。
在Kudu中创建新表时,必须定义一个分区模式来预拆分表。要使用的最佳分区模式取决于数据的结构和数据访问模式。
CREATE TABLE my_first_table
(id BIGINT,name STRING,PRIMARY KEY(id)
)
PARTITION BY HASH PARTITIONS 16
STORED AS KUDU;
TBLPROPERTIES ('kudu.num_tablet_replicas' = '3')
2.1 CTAS(CREATE TABLE AS SELECT)
可以通过查询Impala中的任何其他表来创建表。下面的示例将现有表中的所有行导入到新的Kudu表中。
CREATE TABLE new_table
PRIMARY KEY (ts, name)
PARTITION BY HASH(name) PARTITIONS 8
STORED AS KUDU
AS SELECT ts, name, value FROM old_table;
2.2 创建范围分区表
可以为一个或多个主键列指定范围分区。Kudu中的范围分区允许根据所选分区键的特定值或值范围拆分表。这允许在写并行性和扫描效率之间取得平衡。
CREATE TABLE customers (state STRING,name STRING,purchase_count int,PRIMARY KEY (state, name)
)
PARTITION BY RANGE (state)
(PARTITION VALUE = 'al',PARTITION VALUE = 'ak',PARTITION VALUE = 'ar'
)
STORED AS KUDU;
需要使用范围分区的场景:
-
时间序列数据:如果你有按时间排序的大量数据,例如日志或传感器读数,你可以将表按照时间范围进行分区。这样做可以使查询特定时间段内的数据更高效,并且支持更快速地插入新数据。
-
范围查询:如果你经常需要执行基于某个范围条件(如价格、日期等)进行过滤和聚合操作的查询,那么根据该条件对表进行分区会显著提升性能。通过只扫描相关分区而不是整个表格来执行这些操作。
-
地理空间数据:如果你处理具有地理位置信息(如经度和纬度)的大型数据库,并且希望根据空间距离或边界框来过滤结果集,则将表格按照地理坐标划分为多个子集可能非常有效。
-
大规模并行加载/导出:当需要从外部源加载或导出大量数据时,在Kudu中使用Ranger partitioning 可以实现并行化处理。每个任务负责一个或多个单独定义了较小范围值域(range) 的子集, 这样就允许同时处理多项任务,提高了数据加载和导出的效率。
2.3 创建哈希分区表
可以通过哈希将其分布到特定数量的分区中,而不是按照显式的范围分布或与范围分布结合使用。可以指定要进行分区的主键列,以及要使用的分区数量。通过对指定的键列进行哈希来分发行。假设被哈希的值本身没有表现出明显的倾斜,这将有助于将数据均匀地分布在所有分区上。
使用哈希分区时,通常需要指定一个或多个列作为哈希分区键。这些列的值将用于计算行记录所属的哈希分区。如果在创建表时未显式指定哈希列,则默认情况下会选择所有主键作为哈希分区键。
CREATE TABLE cust_behavior (id BIGINT,sku STRING,salary STRING,edu_level INT,usergender STRING,city STRING,postcode STRING,last_purchase_price FLOAT,last_purchase_date BIGINT,category STRING,rating INT,fulfilled_date BIGINT,PRIMARY KEY (id, sku)
)
PARTITION BY HASH PARTITIONS 16
STORED AS KUDU;
PARTITION BY HASH (id) PARTITIONS 4, HASH (sku) PARTITIONS 4 等同于 PARTITION BY HASH PARTITIONS 16
需要使用哈希分区的场景:
-
均匀分布的数据:如果你有一个具有均匀分布的大型表格,并且需要对其进行随机访问或查询操作,那么使用哈希分区是一个不错的选择。通过将行键(Row Key)应用哈希函数并将结果映射到不同的分区,可以实现数据在各个节点上均匀存储和负载平衡。
-
并行处理:当需要以并行方式执行大规模加载、导入或转换任务时,使用哈希分区可以有效地划定工作单元。每个任务负责处理特定范围内的数据子集,在这种情况下,采用基于哈希值进行划片会更加合适。
-
随机写入和读取:如果你经常执行随机写入和读取操作,并且没有明确按照某个顺序来访问数据,则使用哈希分区可能更为高效。由于每条记录都被映射到唯一的部署位置,在插入新记录时避免了热点问题,并且能够实现良好地负载平衡。
-
数据扩展性要求高:当面对快速增长、海量数据集以及未来可能出现扩展需求时,采用基于哈希的分区策略可以提供更好的数据扩展性。通过增加或减少分区数,可以轻松地调整存储容量和查询性能。
2.4 同时使用范围分区和哈希分区
如果经常查询一个值的范围,那么可以通过将哈希分区与范围分区结合使用来优化。
CREATE TABLE cust_behavior (id BIGINT,sku STRING,salary STRING,edu_level INT,usergender STRING,city STRING,postcode STRING,last_purchase_price FLOAT,last_purchase_date BIGINT,category STRING,rating INT,fulfilled_date BIGINT,PRIMARY KEY (id, sku)
)
PARTITION BY HASH (id) PARTITIONS 4,
RANGE (sku)
(PARTITION VALUES < 'g',PARTITION 'g' <= VALUES < 'o',PARTITION 'o' <= VALUES < 'u',PARTITION 'u' <= VALUES
)
STORED AS KUDU;
2.5 非覆盖范围分区
Kudu支持使用非覆盖范围分区,它可用于解决以下场景:
- 对于时间序列数据或其他需要考虑不断增加的主键的模式,提供旧数据的tablet的大小将相对固定,而接收新数据的tablet将无限制地增长。
- 如果希望根据类别(如销售区域或产品类型)对数据进行分区,而不需要覆盖范围分区,则必须提前了解所有分区,或者在需要添加或删除分区(如引入或消除产品类型)时手动重新创建表。
CREATE TABLE sales_by_year (year INT, sale_id INT, amount INT,PRIMARY KEY (year, sale_id)
)
PARTITION BY RANGE (year) (PARTITION VALUE = 2012,PARTITION VALUE = 2013,PARTITION VALUE = 2014,PARTITION VALUE = 2015,PARTITION VALUE = 2016
)
STORED AS KUDU;
2.5.1 查看范围分区
SHOW RANGE PARTITIONS sales_by_year;
2.5.2 添加范围分区
ALTER TABLE sales_by_year ADD RANGE PARTITION VALUE = 2017;ALTER TABLE sales_by_year ADD RANGE PARTITION 2018 <= VALUES < 2021;ALTER TABLE sales_by_year ADD RANGE PARTITION 2009 <= VALUES < 2012;
2.5.3 删除范围分区
ALTER TABLE sales_by_year DROP RANGE PARTITION VALUE = 2012;ALTER TABLE sales_by_year DROP RANGE PARTITION 2009 <= VALUES < 2012;
3. 增删改
3.1 插入操作
3.1.1 插入一行或多行
INSERT INTO sales_by_year VALUES (2018, 255, 255);
INSERT INTO sales_by_year VALUES (2019, 255, 255), (2020, 255, 255);
INSERT INTO sales_by_year (year, sale_id, amount) VALUES (2021, 256, 256), (2022, 256, 256);
3.1.2 批量插入
从Impala和Kudu的角度来看,通常表现最好的方法是使用Impala中的子单元导入数据。
-
如果数据尚未在Impala中,一种策略是从文本文件(如TSV或CSV文件)导入数据。
-
创建Kudu表,注意指定为主键的列不能有空值。
-
通过查询包含原始数据的表向Kudu表中插入值,示例如下:
INSERT INTO my_kudu_table SELECT * FROM legacy_data_import_table;
3.2 更新操作
UPDATE sales_by_year SET amount=500 where year=2018;
3.3 插入或更新操作
UPSERT INTO sales_by_year VALUES (2018, 255, 500);
UPSERT INTO sales_by_year VALUES (2019, 255, 500), (2020, 255, 500);
UPSERT INTO sales_by_year (year, sale_id, amount) VALUES (2021, 256, 500), (2022, 256, 500);
3.4 删除操作
DELETE FROM sales_by_year WHERE year=2018;
4. 重命名 Impala 映射表
ALTER TABLE my_table RENAME TO my_new_table;
使用语句重命名表只会重命名 Impala 映射表,而不管该表是内部表还是外部表。 这样可以避免对可能访问基础 Kudu 表的其他应用程序造成干扰。
5. 重命名内部表的基础 Kudu 表
在 CDH 5.14 及更低版本中,如果表是内部表,则可以通过更改属性来重命名基础 Kudu 表:kudu.table_name
ALTER TABLE my_internal_table
SET TBLPROPERTIES('kudu.table_name' = 'new_name')
6. 将外部表重新映射到其他 Kudu 表
如果另一个应用程序在 Impala 下重命名了 Kudu 表,则可以重新映射外部表以指向不同的 Kudu 表名称。
ALTER TABLE my_external_table_
SET TBLPROPERTIES('kudu.table_name' = 'some_other_kudu_table')
7. 更改 Kudu 主地址
ALTER TABLE my_table SET TBLPROPERTIES('kudu.master_addresses' = 'kudu-original-master.example.com:7051,kudu-new-master.example.com:7051');
8. 将内部管理的表更改为外部
ALTER TABLE my_table SET TBLPROPERTIES('EXTERNAL' = 'TRUE');
9. 使用 Impala 删除 Kudu 表
如果该表是在 Impala 中创建为内部表的,则使用 ,标准语法会删除 基础 Kudu 表及其所有数据。如果该表是作为外部表创建的,则使用 ,删除 Impala 和 Kudu 之间的映射,但 Kudu 表及其所有数据保持不变。要将外部表更改为内部表,反之亦然,请参阅更改表 属性。CREATE TABLEDROP TABLECREATE EXTERNAL TABLE
DROP TABLE my_first_table;
总结
通过本教程,您已经掌握了在Impala中使用SQL语法对Kudu进行各种操作的方法。无论是创建新的Kudu内部或外部表,还是执行数据增删改查等常见任务,在这里都有详细说明与示例供参考。同时也介绍了一些高级功能如重命名、更改主地址等特殊情况下需要用到的技巧。希望这些知识能够帮助您更好地理解并应用Impala与Kudu相结合进行大规模数据处理与管理。
希望本教程对您有所帮助!如有任何疑问或问题,请随时在评论区留言。感谢阅读!