Doris

基本概念

基于MMP架构得事实分析型数据库

MPP ( Massively Parallel Processing ),即大规模并行处理,

MPP 是将任务并行的分散到多个服务器和节点上,在每个节点上计算完成后,

将各自部分的结果汇总在一起得到最终的结果 ( 与 Hadoop 相似 )。

使用场景

多作为数仓查询层使用

项目架构

Doris 的架构很简洁,只设 FE(Frontend)、BE(Backend)两种角色、两个进程。

  • Frontend(FE),主要负责用户请求的接入、查询解析规划、元数据的管理、节点管理相关工作。
  • Backend(BE),主要负责数据存储、查询计划的执行
  • 类比hive, FE=matestore BE=HDFS

架构图

在这里插入图片描述

FE和BE均支持横向扩展,两个进程通过一致性协议保证高可用,数据高可靠

FE: 主要有三个角色:Leader、follower、Observer

  • follower为从节点,一般为奇数个,因为元数据写入需要多数 Follower 节点写入成功,才算成功
  • Leader为主节点,是特殊得follower节点,众多follower节点选举出来得
  • Observer为观察者节点,不会参与选举,同步已经成功写入的元数据日志,并且提供元数据读服务,不会参与写得逻辑
  • 通常使用 1 follower + 2 observer ,可减少多follower一致性协议出错,高并发查询则observer

** 查询引擎**

  • 查询基于MPP,节点间和节点内都并行执行,也支持多个大表的分布式 Shuffle Join
  • 向量化查询,所有数据均可按列式部署

在这里插入图片描述

使用接口

Doris 采用 MySQL 协议,高度兼容 MySQL 语法,支持标准 SQL,用户可以通过各类客户端工具来访问 Doris,并支持与 BI 工具的无缝对接。Doris 当前支持多种主流的 BI 产品,包括不限于 SmartBI、DataEase、FineBI、Tableau、Power BI、SuperSet 等,只要支持 MySQL 协议的 BI 工具,Doris 就可以作为数据源提供查询支持

建表默认语句

CREATE TABLE IF NOT EXISTS table_name
(
    `user_id` LARGEINT NOT NULL COMMENT "用户id",
    `date` DATE NOT NULL COMMENT "数据灌入日期时间",
    `timestamp` DATETIME NOT NULL COMMENT "数据灌入的时间戳",
    `city` VARCHAR(20) NOT NULL COMMENT "用户所在城市",
    `age` SMALLINT COMMENT "用户年龄",
    `sex` TINYINT COMMENT "用户性别",
    `last_visit_date` DATETIME REPLACE DEFAULT "1970-01-01 00:00:00" COMMENT "用户最后一次访问时间",
    `cost` BIGINT SUM DEFAULT "0" COMMENT "用户总消费",
    `max_dwell_time` INT MAX DEFAULT "0" COMMENT "用户最大停留时间",
    `min_dwell_time` INT MIN DEFAULT "99999" COMMENT "用户最小停留时间"
)
--引擎,默认olap,也可以为 mysql、broker、es 
ENGINE=olap   
--数据模型,当前含义为聚合模式,且key为 `user_id`, `date`, `timestamp`, `city`, `age`, `sex`结合
AGGREGATE KEY(`user_id`, `date`, `timestamp`, `city`, `age`, `sex`)
--数据分区,当前含义为根据城市分区保存
PARTITION BY LIST(`city`)
(
    PARTITION `p_cn` VALUES IN ("Beijing", "Shanghai", "Hong Kong"),
    PARTITION `p_usa` VALUES IN ("New York", "San Francisco"),
    PARTITION `p_jp` VALUES IN ("Tokyo")
)
--数据分桶,当前含义为根据城市分区后根据user_id分桶保存
DISTRIBUTED BY HASH(`user_id`) BUCKETS 16
-- 设置表属性
-- replication_num为分片数量,默认3个,应该满足replication_num<=BE的个数
-- storage_medium数据存储介质 ssd盘
-- storage_cooldown_time 设定到期时间
-- 当前含义为 相同数据会备份到3个BE里,且存储在ssd盘,2018-01-01 12:00:00会自动迁移到 HDD 存储上
PROPERTIES
(
    "replication_num" = "3",
    "storage_medium" = "SSD",
    "storage_cooldown_time" = "2018-01-01 12:00:00"
);

数据模型

数据以表(Table)得形式存储数据,一张表包含行(Row)与列(Column)

Row即用户的一行数据

Column 用于描述一行数据中不同的字段。其中分为两大类key和value

  • key : 建表语句中的关键字’unique key’或’aggregate key’或’duplicate key’定义得
  • value : 没有关键字修饰得

Doris 的数据模型主要分为3类:

Aggregate

Aggregate修饰得字段集合聚合成一条(类似mysql得groupBy),value集合会根据字段得聚合方式聚合

  1. SUM:求和,多行的 Value 进行累加。
  2. REPLACE:替代,下一批数据中的 Value 会替换之前导入过的行中的 Value。
  3. MAX:保留最大值。
  4. MIN:保留最小值。
  5. REPLACE_IF_NOT_NULL:非空值替换。和 REPLACE 的区别在于对于null值,不做替换。
  6. HLL_UNION:HLL 类型的列的聚合方式,通过 HyperLogLog 算法聚合。
  7. BITMAP_UNION:BIMTAP 类型的列的聚合方式,进行位图的并集聚合。

例:

-- 创建表
-- key : `user_id`, `date`, `city`, `age`, `sex` (设置语句:AGGREGATE KEY(`user_id`, `date`, `city`, `age`, `sex`) )
-- value : last_visit_date(REPLACE),cost (SUM ),max_dwell_time(MAX),min_dwell_time(MIN)
CREATE TABLE IF NOT EXISTS table_name
(
    `user_id` LARGEINT NOT NULL COMMENT "用户id",
    `date` DATE NOT NULL COMMENT "数据灌入日期时间",
    `city` VARCHAR(20) COMMENT "用户所在城市",
    `age` SMALLINT COMMENT "用户年龄",
    `sex` TINYINT COMMENT "用户性别",
    `last_visit_date` DATETIME REPLACE DEFAULT "1970-01-01 00:00:00" COMMENT "用户最后一次访问时间",
    `cost` BIGINT SUM DEFAULT "0" COMMENT "用户总消费",
    `max_dwell_time` INT MAX DEFAULT "0" COMMENT "用户最大停留时间",
    `min_dwell_time` INT MIN DEFAULT "99999" COMMENT "用户最小停留时间"
)
AGGREGATE KEY(`user_id`, `date`, `city`, `age`, `sex`) 
DISTRIBUTED BY HASH(`user_id`) BUCKETS 1
PROPERTIES (
"replication_allocation" = "tag.location.default: 1"
);
-- 插入语句
insert into table_name values
(10000,"2017-10-01","北京",20,0,"2017-10-01 06:00:00",20,10,10),
(10000,"2017-10-01","北京",20,0,"2017-10-01 07:00:00",15,2,2),
(10001,"2017-10-01","北京",30,1,"2017-10-01 17:05:45",2,22,22),
(10002,"2017-10-02","上海",20,1,"2017-10-02 12:59:12",200,5,5),
(10003,"2017-10-02","广州",32,0,"2017-10-02 11:20:00",30,11,11),
(10004,"2017-10-01","深圳",35,0,"2017-10-01 10:00:15",100,3,3),
(10004,"2017-10-03","深圳",35,0,"2017-10-03 10:20:22",11,6,6);
-- 相同key
(10000,"2017-10-01","北京",20,0,"2017-10-01 06:00:00",20,10,10)
(10000,"2017-10-01","北京",20,0,"2017-10-01 07:00:00",15,2,2)
-->(10000,"2017-10-01","北京",20,0,"2017-10-01 07:00:00",35,10,2)
-- 不同key
(10000,"2017-10-01","北京",20,0,"2017-10-01 06:00:00",20,10,10)
(10001,"2017-10-01","北京",30,1,"2017-10-01 17:05:45",2,22,22)
--> (10000,"2017-10-01","北京",20,0,"2017-10-01 06:00:00",20,10,10)
(10001,"2017-10-01","北京",30,1,"2017-10-01 17:05:45",2,22,22)
Unique

对数据唯一性要求,采取写时合并(merge on write),通过在写入时做一些额外的工作,实现了最优的查询性能。 写时合并将在未来替换读时合并成为Unique模型的默认实现方式

Aggregate差别在:

  • 查询速度变快,在开启了写时合并选项的Unique表上,数据在导入阶段就会去将被覆盖和被更新的数据进行标记删除,同时将新的数据写入新的文件。在查询的时候, 所有被标记删除的数据都会在文件级别被过滤掉,读取出来的数据就都是最新的数据,消除掉了读时合并中的数据聚合过程,并且能够在很多情况下支持多种谓词的下推。因此在许多场景都能带来比较大的性能提升,尤其是在有聚合查询的情况下
  • Aggregate只聚合不含有排序,unique带有排序也带有聚合

语法:

-- 添加唯一键:UNIQUE KEY(`user_id`, `username`)
CREATE TABLE IF NOT EXISTS table_name
(
    `user_id` LARGEINT NOT NULL COMMENT "用户id",
    `username` VARCHAR(50) NOT NULL COMMENT "用户昵称",
    `city` VARCHAR(20) COMMENT "用户所在城市",
    `age` SMALLINT COMMENT "用户年龄",
    `sex` TINYINT COMMENT "用户性别",
    `phone` LARGEINT COMMENT "用户电话",
    `address` VARCHAR(500) COMMENT "用户地址",
    `register_time` DATETIME COMMENT "用户注册时间"
)
UNIQUE KEY(`user_id`, `username`)
DISTRIBUTED BY HASH(`user_id`) BUCKETS 1
PROPERTIES (
"replication_allocation" = "tag.location.default: 1",
"enable_unique_key_merge_on_write" = "true"
);
Duplicate

在某些多维分析场景下,数据既没有主键,也没有聚合需求。类似mysql得不设唯一键得数据存储,自带排序,且符合前缀索引建立,一般四个以内

语法

-- 添加唯一键:UNIQUE KEY(`user_id`, `username`)
CREATE TABLE IF NOT EXISTS table_name
(
    `user_id` LARGEINT NOT NULL COMMENT "用户id",
    `username` VARCHAR(50) NOT NULL COMMENT "用户昵称",
    `city` VARCHAR(20) COMMENT "用户所在城市",
    `age` SMALLINT COMMENT "用户年龄",
    `sex` TINYINT COMMENT "用户性别",
    `phone` LARGEINT COMMENT "用户电话",
    `address` VARCHAR(500) COMMENT "用户地址",
    `register_time` DATETIME COMMENT "用户注册时间"
)
DUPLICATE KEY(`user_id`, `username`)
DISTRIBUTED BY HASH(`user_id`) BUCKETS 1
PROPERTIES (
"replication_allocation" = "tag.location.default: 1",
"enable_unique_key_merge_on_write" = "true"
);

数据表物理结构

table:数据表

Partition:分区 (逻辑上最小的管理单元。数据的导入与删除,仅能针对一个 Partition 进行)

Tablet:数据分桶,物理上独立存储

Row:数据行

Column:列 (描述行数据的不同字段)

关系:

table->多个Partition

Partition->多个Tablet

Tablet->若干row

数据划分

类似于MySql分库分表概念

Doris支持两层的数据划分。第一层是 Partition,支持 Range 和 List 的划分方式。第二层是 Bucket(Tablet),支持 Hash 和 Random 的划分方式。

如果已划分区且导入的数据不存在分区内,则无法导入

Partition(分区)

基本概念:

  • Partition 列可以指定一列或多列,分区列必须为 KEY 列。
  • 不论分区列是什么类型,在写分区值时,都需要加双引号。
  • 分区数量理论上没有上限。
  • 当不使用 Partition 建表时,系统会自动生成一个和表名同名的,全值范围的 Partition。该 Partition 对用户不可见,并且不可删改。
  • 创建分区时不可添加范围重叠的分区。
  • 如果导入的数据不存在分区内,则无法导入
  • 是否分区这个属性在建表时确定,之后不可更改。即对于分区表,可以在之后的使用过程中对分区进行增删操作,而对于无分区的表,之后不能再进行增加分区等操作。

Range(范围,限定好列的范围,符合条件的进入对应partition)

  • 分区列通常为时间列,以方便的管理新旧数据。
  • Range 分区支持的列类型:[DATE,DATETIME,TINYINT,SMALLINT,INT,BIGINT,LARGEINT]
  • Partition 支持通过 VALUES LESS THAN (...) 仅指定上界,系统会将前一个分区的上界作为该分区的下界,生成一个左闭右开的区间。也支持通过 VALUES [...) 指定上下界,生成一个左闭右开的区
  • 批量新增分区:FROM (“2022-01-03”) TO (“2022-01-06”) INTERVAL 1 DAY ->每隔一天生成一个分区,且左开右毕
  • 可使用动态分区 详情请至PROPERTIES

示例:

-- 单列 
-- date<2017-02-01 进入p201701分区
-- 2017-02-01<date<2017-03-01进入p201702分区
-- 2017-03-01<date<2017-04-01进入p201703分区
PARTITION BY RANGE(`date`)
(
    PARTITION `p201701` VALUES LESS THAN ("2017-02-01"), 
    PARTITION `p201702` VALUES LESS THAN ("2017-03-01"),
    PARTITION `p201703` VALUES LESS THAN ("2017-04-01")
)
-- 多列
-- date<2017-02-01 & money<1000  进入p201701分区
-- 2017-02-01<date<2017-03-01 & 1000<money<2000 进入p201702分区
-- 2017-03-01<date<2017-04-01 & 2000<money<3000 进入p201703分区
-- 2017-04-01<date<2017-05-01 & money>3000 进入p201704分区
PARTITION BY RANGE(`date``money`)
(
    PARTITION `p201701` VALUES LESS THAN ("2017-02-01",1000), 
    PARTITION `p201702` VALUES LESS THAN ("2017-03-01",2000),
    PARTITION `p201703` VALUES LESS THAN ("2017-04-01",3000),
	PARTITION `p201704` VALUES LESS THAN ("2017-05-01")
)

List分区(类似于枚举类型,等于该类型的进入对应partition)

  • 分区列支持 BOOLEAN, TINYINT, SMALLINT, INT, BIGINT, LARGEINT, DATE, DATETIME, CHAR, VARCHAR 数据类型,分区值为枚举值。只有当数据为目标分区枚举值其中之一时,才可以命中分区。
  • Partition 支持通过 VALUES IN (...) 来指定每个分区包含的枚举值

示例:

-- 单列 
-- sex 为 "男"或"男性"都进入p1_man分区
PARTITION BY List(`sex`)
(
    PARTITION `p1_man` VALUES IN   ("男","男性"), 
    PARTITION `p1_woman` VALUES IN  ('女',"女性")
)

-- 多列 
-- p1_man 存储 
--①男+18 ②男性+18 ③男+18岁 ④男性+18岁
PARTITION BY List(`sex`,`age`)
(
    PARTITION `p1_man` VALUES IN   (("男","男性"),("18","18岁")), 
    PARTITION `p1_woman` VALUES IN  (('女',"女性",("18","18岁"))
)
Bucket(分桶)

数据划分规则,类似于按用户id分表,

  • 如果存在Partition,则对每个Partition进行数据划分

  • 如果不存在,则对整个Table的数据划分

  • 分桶列可以是多列,Aggregate 和 Unique 模型必须为 Key 列,Duplicate 模型可以是 key 列和 value 列

  • 桶列可以和 Partition 列相同或不同。

  • 分桶列的选择,是在 查询吞吐查询并发 之间的一种权衡:

    1. 如果选择多个分桶列,则数据分布更均匀。如果一个查询条件不包含所有分桶列的等值条件,那么该查询会触发所有分桶同时扫描,这样查询的吞吐会增加,单个查询的延迟随之降低。这个方式适合大吞吐低并发的查询场景。
    2. 如果仅选择一个或少数分桶列,则对应的点查询可以仅触发一个分桶扫描。此时,当多个点查询并发时,这些查询有较大的概率分别触发不同的分桶扫描,各个查询之间的IO影响较小(尤其当不同桶分布在不同磁盘上时),所以这种方式适合高并发的点查询场景
  • AutoBucket: 根据数据量,计算分桶数。 对于分区表,可以根据历史分区的数据量、机器数、盘数,确定一个分桶。

    可在PROPERTIES设置”estimate_partition_size" = “100G”

  • 分桶的数量理论上没有上限

分桶语句;

--不加分区
DISTRIBUTED BY HASH(`user_id`) BUCKETS 16 --根据userid分16个桶
-- 分区 
-- 根据城市分区,然后分区内的row根据userid分成16个桶
PARTITION BY LIST(`city`)
(
    PARTITION `p_cn` VALUES IN ("Beijing", "Shanghai", "Hong Kong"),
    PARTITION `p_usa` VALUES IN ("New York", "San Francisco"),
    PARTITION `p_jp` VALUES IN ("Tokyo")
)
DISTRIBUTED BY HASH(`user_id`) BUCKETS 16

Partition 和 Bucket 的数量和数据量

  • 一个表的 Tablet 总数量等于 (Partition num * Bucket num)。
  • 一个表的 Tablet 数量,在不考虑扩容的情况下,推荐略多于整个集群的磁盘数量。
  • 单个 Tablet 的数据量理论上没有上下界,但建议在 1G - 10G 的范围内。如果单个 Tablet 数据量过小,则数据的聚合效果不佳,且元数据管理压力大。如果数据量过大,则不利于副本的迁移、补齐,且会增加 Schema Change 或者 Rollup 操作失败重试的代价(这些操作失败重试的粒度是 Tablet)。
  • 当 Tablet 的数据量原则和数量原则冲突时,建议优先考虑数据量原则。
  • 在建表时,每个分区的 Bucket 数量统一指定。但是在动态增加分区时(ADD PARTITION),可以单独指定新分区的 Bucket 数量。可以利用这个功能方便的应对数据缩小或膨胀。
  • 一个 Partition 的 Bucket 数量一旦指定,不可更改。所以在确定 Bucket 数量时,需要预先考虑集群扩容的情况。比如当前只有 3 台 host,每台 host 有 1 块盘。如果 Bucket 的数量只设置为 3 或更小,那么后期即使再增加机器,也不能提高并发度。
  • 举一些例子:假设在有10台BE,每台BE一块磁盘的情况下。如果一个表总大小为 500MB,则可以考虑4-8个分片。5GB:8-16个分片。50GB:32个分片。500GB:建议分区,每个分区大小在 50GB 左右,每个分区16-32个分片。5TB:建议分区,每个分区大小在 50GB 左右,每个分区16-32个分片。

注:表的数据量可以通过 SHOW DATA 命令查看,结果除以副本数,即表的数据量。

PROPERTIES

--PROPERTIES属性设置
PROPERTIES
(
     -- 动态分区 
    "dynamic_partition.enable" = "true", --是否开启 Doris 的动态分区功能
    "dynamic_partition.time_unit" = "DAY",-- 动态分区调度的单位 HOUR、DAY、WEEK、MONTH、YEAR
    "dynamic_partition.time_zone" ="Asia/Shanghai" -- 时区 默认为当前系统时区
    "dynamic_partition.start" = "-7", --动态分区的起始偏移为负数。
    "dynamic_partition.end" = "3", --动态分区的结束偏移,为正数
    "dynamic_partition.prefix" = "p", --动态创建的分区名前缀
    "dynamic_partition.buckets" = "32" --动态创建的分区所对应的分桶数量。
    "dynamic_partition.replication_num"="3" --副本数量,
    "dynamic_partition.start_day_of_week"="1" --每周起始点(start_day_of_week) 每月起始点(start_day_of_month)
	"dynamic_partition.create_history_partition"="false",--: 是否创建历史分区。
	"dynamic_partition.history_partition_num"="1",--: 指定创建历史分区的数量。
	"dynamic_partition.reserved_history_periods"="1",--dynamic_partition.reserved_history_periods: 用于指定保留的历史分区的时间段
	-- 基本配置 
	"replication_num"="3" , --副本数量     默认为3
	"storage_medium" = "SSD",-- 数据存储介质  
	"storage_cooldown_time" = "2020-11-20 00:00:00" --到期时间 到期自动转到HDD存储上
	"bloom_filter_columns"= "k1, k2, k3",--Bloom Filter 索引的列名称列表。各个列的 Bloom Filter 索引是独立的,并不是组合索引
	"compression"="zstd",--压缩方式
	"disable_auto_compaction" = "false",--自动compaction。compaction进程会跳过这个表的所有tablet
 	--自动分桶
	"estimate_partition_size" = "100G"
 
)

数据缓存

缓存策略

  1. SQLCache
    sql签名+记录查询的分区id+分区最新版本 作为缓存key,数据/sql/分区变更均可能无法名字,适用于记录不变更,且查询重复,类似大屏

  2. PartitionCache
    缓存原理:
    a. sql拆分,每一个查询条件对应一个结果集
    b. 区域拆分为只读分区与可更新分区,对于变动的结果集放入可更新分区,对于数据不变动的结果放入只读分区缓存起来

  3. 缓存设置

--SQLCache开启
cache_enable_sql_mode=true 
--PartitionCache开启
cache_enable_partition_mode=true
--缓存时间 
-- 两种缓存开启,查询语句均能命中缓存, SQLCache优先,间隔版本时间超过失效时间,则使用PartitionCache
cache_last_version_interval_second=900
  1. 监控
query_table            //Query中有表的数量
query_olap_table       //Query中有Olap表的数量
cache_mode_sql         //识别缓存模式为sql的Query数量
cache_hit_sql          //模式为sql的Query命中Cache的数量
query_mode_partition   //识别缓存模式为Partition的Query数量
cache_hit_partition    //通过Partition命中的Query数量
partition_all          //Query中扫描的所有分区
partition_hit          //通过Cache命中的分区数量

Cache命中率     = (cache_hit_sql + cache_hit_partition) / query_olap_table
Partition命中率 = partition_hit / partition_all

query_cache_memory_total_byte       //Cache内存大小
query_query_cache_sql_total_count   //Cache的SQL的数量
query_cache_partition_total_count   //Cache分区数量

SQL平均数据大小       = cache_memory_total / cache_sql_total
Partition平均数据大小 = cache_memory_total / cache_partition_total
  1. 优化
    FE:合理的设置每次缓存的大小(cache_result_max_data_size),避免单次查询大批数据进入缓存,占用内存
    BE
    a. 合理配置单sql的最大分区数量(cache_max_partition_count),默认时间分区可缓存2年,如果需要缓存更长时间,则需要调增参数
    b. 缓存内存设置,有两个参数query_cache_max_size和query_cache_elasticity_size两部分组成(单位MB),内存超过query_cache_max_size + cache_elasticity_size会开始清理,并把内存控制到query_cache_max_size以下。可以根据BE节点数量,节点内存大小,和缓存命中率来设置这两个参数

BROKER

用于支持 Doris 读写远端存储上的文件和目录,是一个数据通道,正常存在多个,汇成一个组

架构图
在这里插入图片描述

冷热分层

长期不变动Partition的数据设置freeze time,表示多久这个Partition会被freeze,并且定义freeze之后存储的remote storage的位置。在be上daemon线程会周期性的判断表是否需要freeze,若freeze后会将数据上传到s3和hdfs上

  1. 冷数据存储对象存储,查询时从远程缓存到本地
  2. 冷数据删除则会删除远程数据
  3. 缓存优化保证冷热查询性能,be线程池优化,区分查询时冷热数据,减少延迟
Storage policy

存储策略是使用冷热分层功能的入口,用户只需要在建表或使用doris过程中,给表或分区关联上storage policy,即可以使用冷热分层的功能

-- S3
--创建远程资源
CREATE RESOURCE "remote_s3"
PROPERTIES
(
 "type" = "s3",
    "s3.endpoint" = "bj.s3.com",
    "s3.region" = "bj",
    "s3.bucket" = "test-bucket",
    "s3.root.path" = "path/to/root",
    "s3.access_key" = "bbb",
    "s3.secret_key" = "aaaa",
    "s3.connection.maximum" = "50",
    "s3.connection.request.timeout" = "3000",
    "s3.connection.timeout" = "1000"
);

CREATE STORAGE POLICY test_policy
PROPERTIES(
    "storage_resource" = "remote_s3",
    "cooldown_ttl" = "1d"
);
-- 使用远程资源
  CREATE TABLE IF NOT EXISTS create_table_use_created_policy (
    k1 BIGINT,
    k2 LARGEINT,
    v1 VARCHAR(2048)
    )
    UNIQUE KEY(k1)
    DISTRIBUTED BY HASH (k1) BUCKETS 3
    PROPERTIES(
    --指定该表的缓存资源为S3
    "storage_policy" = "test_policy"
    );
-- hdfs
CREATE RESOURCE "remote_hdfs" PROPERTIES (
        "type"="hdfs",
        "fs.defaultFS"="fs_host:default_fs_port",
        "hadoop.username"="hive",
        "hadoop.password"="hive",
        "dfs.nameservices" = "my_ha",
        "dfs.ha.namenodes.my_ha" = "my_namenode1, my_namenode2",
        "dfs.namenode.rpc-address.my_ha.my_namenode1" = "nn1_host:rpc_port",
        "dfs.namenode.rpc-address.my_ha.my_namenode2" = "nn2_host:rpc_port",
        "dfs.client.failover.proxy.provider" = "org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider"
    );

    CREATE STORAGE POLICY test_policy PROPERTIES (
        "storage_resource" = "remote_hdfs",
        "cooldown_ttl" = "300"
    )

    CREATE TABLE IF NOT EXISTS create_table_use_created_policy (
    k1 BIGINT,
    k2 LARGEINT,
    v1 VARCHAR(2048)
    )
    UNIQUE KEY(k1)
    DISTRIBUTED BY HASH (k1) BUCKETS 3
    PROPERTIES(
    "storage_policy" = "test_policy"
    );
  • 28
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值