Doris

247 阅读7分钟

Doris表结构不能创建索引,按照你建表语句的列定义自动创建前缀排序索引

Doris数据类型

三种模型

1. 明细模型

明细模型数据完全一样也会保留

CREATE TABLE example_db.table_hash
(
    k1 DATE,
    k2 DECIMAL(10, 2) DEFAULT "10.5",
    k3 CHAR(10) COMMENT "string column",
    k4 INT NOT NULL DEFAULT "1" COMMENT "int column"
)
DUPLICATE KEY(k1, k2) -- 明细模型主键
COMMENT "my first table"
PARTITION BY RANGE(k1)   -- 静态分区
(
    PARTITION p1 VALUES LESS THAN ("2020-02-01"),
    PARTITION p2 VALUES LESS THAN ("2020-03-01"),
    PARTITION p3 VALUES LESS THAN ("2020-04-01")
)
DISTRIBUTED BY HASH(k1) BUCKETS 32  -- 分桶
PROPERTIES (                     -- 其他参数配置
    "replication_num" = "1"
);

2. 唯一模型

唯一模型主键完全一样的只保留最后一份的数据

CREATE TABLE example_db.table_hash
(
    k1 BIGINT,
    k2 LARGEINT,
    v1 VARCHAR(2048),
    v2 SMALLINT DEFAULT "10"
)
UNIQUE KEY(k1, k2)
DISTRIBUTED BY HASH (k1, k2) BUCKETS 32
PROPERTIES(
    "storage_medium" = "SSD",
    "storage_cooldown_time" = "2015-06-04 00:00:00"
);

3. 聚合模型

聚合模型有 MIN, MAX, SUM,REPLACE,REPLACE_IF_NOT_NULL

CREATE TABLE IF NOT EXISTS example_tbl_agg1
(
    `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 10
PROPERTIES (
"replication_allocation" = "tag.location.default: 3"
);

分区

静态分区

  • Range分区
    • range
      -- 定义的左闭右开区间
      PARTITION BY RANGE(`date`)
      (
          PARTITION `p201701` VALUES [("2017-01-01"),  ("2017-02-01")),
          PARTITION `p201702` VALUES [("2017-02-01"), ("2017-03-01")),
          PARTITION `p201703` VALUES [("2017-03-01"), ("2017-04-01"))
      )
      
    • less range
      -- 仅定义分区上界。下界由上一个分区的上界决定。
      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"),
          PARTITION `p2018` VALUES [("2018-01-01"), ("2019-01-01")),
          PARTITION `other` VALUES LESS THAN (MAXVALUE)
      )
      
    • BATCH RANGE
      PARTITION BY RANGE(int_col)                                                           
      (                     
          FROM (start_num) TO (end_num) INTERVAL interval_value   
      )
      
      PARTITION BY RANGE(date_col)
      (                                                                       
          FROM ("start_date") TO ("end_date") INTERVAL num YEAR | num MONTH | num WEEK | num DAY1 HOUR                                                
      )
      
      -- 例子
      PARTITION BY RANGE(age)
      (
          FROM (1) TO (100) INTERVAL 10
      )
      
      PARTITION BY RANGE(`date`)
      (
          FROM ("2000-11-14") TO ("2021-11-14") INTERVAL 2 YEAR  -- 从2000年11-14号开始两年一个分区
      )
      
  • List分区
      -- 分区字段和列表完全匹配才成功
      PARTITION BY LIST(id, city)
      (
          PARTITION p1_city VALUES IN (("1", "Beijing"), ("1", "Shanghai")),
          PARTITION p2_city VALUES IN (("2", "Beijing"), ("2", "Shanghai")),
          PARTITION p3_city VALUES IN (("3", "Beijing"), ("3", "Shanghai"))
      )
    

多级分区

-- 建表
create table student_dynamic_partition1 (
    id int,
    time date,
    name varchar(50),
    age int
)
duplicate key(id,time)
PARTITION BY RANGE(`time`, `id`) (
    PARTITION `p201701_1000` VALUES LESS THAN ("2017-02-01", "1000"),
    PARTITION `p201702_2000` VALUES LESS THAN ("2017-03-01", "2000"),
    PARTITION `p201703_all` VALUES LESS THAN ("2017-04-01")
)
DISTRIBUTED BY HASH(id) buckets 10;

-- 插入数据
insert into student_dynamic_partition1 values(200, "2017-01-01",  'a', 11);
insert into student_dynamic_partition1 values( 2000, "2017-01-01", 'a', 11);
insert into student_dynamic_partition1 values(  100, "2017-02-01", 'a', 11);
insert into student_dynamic_partition1 values(  2000, "2017-02-01", 'a', 11);
insert into student_dynamic_partition1 values(  5000,"2017-02-15", 'a', 11);
insert into student_dynamic_partition1 values(  2000,"2017-03-01", 'a', 11);
insert into student_dynamic_partition1 values(  1,"2017-03-10", 'a', 11);
insert into student_dynamic_partition1 values(  100,"2017-04-01", 'a', 11);
insert into student_dynamic_partition1 values(  1000, "2017-05-01",'a', 11);

select * from student_dynamic_partition1;
select * from student_dynamic_partition1 partition(p201701_1000);
select * from student_dynamic_partition1 partition(p201702_2000);
select * from student_dynamic_partition1 partition(p201703_all);

坑点:例如第三条数据,第一个字段恰好属于边界时,第二个字段数据范围内则是该分区内的数据

动态分区

参数解释
dynamic_partition.enable是否开启动态分区特性,可指定 true 或 false,默认为 true
dynamic_partition.time_unit动态分区调度的单位,可指定 HOUR、DAY、WEEK、MONTH。 HOUR,后缀格式为 yyyyMMddHH,分区列数据类型不能为 DATE。DAY,后缀格式为 yyyyMMdd。WEEK,后缀格式为 yyyy_ww。即当前日期属于这一年的第几周。MONTH,后缀格式为 yyyyMM。
dynamic_partition.time_zone动态分区的时区,如果不填写,则默认为当前机器的系统的时区
dynamic_partition.start动态分区的起始偏移,为负数。根据 time_unit 属性的不同,以当天(星期/月)为基准,分区范围在此偏移之前的分区将会被删除。如果不填写默认值为 Interger.Min_VALUE 即-2147483648,即不删除历史分区
dynamic_partition.end动态分区的结束偏移,为正数。根据 time_unit 属性的不同,以当天(星期/月)为基准,提前创建对应范围的分区
dynamic_partition.prefix动态创建的分区名前缀
dynamic_partition.buckets动态创建的分区所对应分桶数量
dynamic_partition.replication_num动态创建的分区所对应的副本数量,如果不填写,则默认为该表创建时指定的副本数量。
dynamic_partition.start_day_of_week当 time_unit 为 WEEK 时,该参数用于指定每周的起始点。取值为 1 到 7。其中 1 表示周一,7 表示周日。默认为 1,即表示每周以周一为起始点
dynamic_partition.start_day_of_month当 time_unit 为 MONTH 时,该参数用于指定每月的起始日期。取值为 1 到 28。其中 1 表示每月 1 号,28 表示每月 28 号。默认为 1,即表示每月以 1 号位起始点。暂不支持以 29、30、31 号为起始日,以避免因闰年或闰月带来的歧义
-- 分区列 time 类型为 DATE,创建一个动态分区规则。
-- 按天分区,只保留最近 7 天的分区,并且预先创建未来 3 天的分区。
create table student_dynamic_partition1 (
    id int,
    time date,
    name varchar(50), age int
)
duplicate key(id,time) PARTITION BY RANGE(time)()
DISTRIBUTED BY HASH(id) buckets 10 
PROPERTIES(
    "dynamic_partition.enable" = "true", 
    "dynamic_partition.time_unit" = "DAY", 
    "dynamic_partition.start" = "-7",
    "dynamic_partition.end" = "3", 
    "dynamic_partition.prefix" = "p", 
    "dynamic_partition.buckets" = "10",
    "replication_num" = "1"
);

ROLLUP

上卷,更粗粒度的聚合 对于这张基表 image.png

image.png

一张Base表可以创建多张ROLLUP表

  • 创建语法
-- 字段前面是 key 字段,后面是聚合字段
alter table [tableName]  add rollup [rollupName](city,age,cost,max_dwell_time,min_d well_time);

在明细模型和唯一模型中rollup失去了粗粒度聚合的作用,只是用来改变表的前缀索引的作用

物化视图

物化视图是将预先计算(定义好的select语句)好的数据集,存储在Doris中的一个特殊的表。 和mysql不同的是,mysql是每次去查询视语句返回结果再次查询,物化视图会把结果保存下来。

CREATE MATERIALIZED VIEW 视图名称 AS selec .....
  1. 物化视图创建成功后,用户的查询不需要发生任何改变,也就是还是查询的 base表。Doris 会根据当前查询的语句去自动选择一个最优的物化视图,从物化视图中读取数据并计算。
  2. 用户可以通过 EXPLAIN 命令来检查当前查询是否使用了物化视图。
  3. 物化视图也会基于原表进行实时更新