StarRocks入门学习<二>

1,346 阅读12分钟

其他更多java基础文章:
java基础学习(目录)


本文为尚硅谷StarRocks视频的整理总结,另外发现一个讲StarRocks的系列博客

1. 物化视图

Materialized Views 表:简称 MVs,物化视图。
在实际的业务中,我们通常需要对数据进行对原始明细数据任意维度的分析以及固定维度聚合分析。两种场景并存的情况下,聚合模型表由于缺失部分明细数据,就无法满足用户对明细数据的分析需求。如果仅建立一个明细模型,虽然可以满足任意维度的分析需求,但对明细数据进行聚合分析时,实时分析性能不佳。若同时建立一个聚合模型和一个明细模型,虽然可以满足性能和任意维度分析,但两表之间本身无关联,需要业务方自行选择分析表,不灵活也不易用。

Base表
CREATE TABLE table11(
    record_id int,
    seller_id int,
    store_id int,
    sale_date date,
    sale_amt bigint
) distributed BY hash(record_id)
properties("replication_num" = "1");

如果我们需要对不同门店的销售量做分析,那么SQL写法为:
SELECT store_id, SUM(sale_amt) FROM table11 GROUP BY store_id;

我们就可以基于table11表创建一张“以售卖门店为分组,对相同售卖门店的销售额求和”的物化视图表table11_mv1
CREATE MATERIALIZED VIEW table11_mv1 AS
    SELECT store_id, SUM(sale_amt)
    FROM table11
    GROUP BY store_id;
    

我们将table11这样的OLAP表称为Base表(或基表),基于Base表我们可以创建物化视图表(MVs表),物化视图的数据组织形式(分区、分桶、存储等)和Base表相同,但物化视图拥有单独的前缀索引。

StarRocks的物化视图对用户是隐式的,当我们查询时,并不需要感知物化视图的存在,也不必显式的指定物化视图的名称,查询优化器会根据查询条件自动判断是否可以路由到相应的物化视图并选择最佳的MVs表,然后重写查询计划进行最优查询。

我们来解析上面的查询:
EXPLAIN SELECT store_id, SUM(sale_amt) FROM table11 GROUP BY store_id;

其中PREAGGREGATION:ON,就表明查询时不需要在StarRocks存储引擎中现场聚合,查询会更快。
rollup:table11_mv1,即为查询命中物化视图table11_mv1:
|0:OlapScanNode
|TABLE:table11
|PREAGGREGATION:ON
|partitions=1/1
|rollup:table11_mv1
|tabletRatio=10/10

对Base表的增量导入都会作用到所有关联的MVs表中,在Base表及其所有的MVs表均完成后,导入才算完成,数据才能被看到(否则导入整体失败,具备原子性)。StarRocks会保证Base表和MVs表之间的数据是一致的,查询Base表和查询MVs表的结果不会存在数据差异。

1.1 物化视图的操作

创建物化视图是一个异步的操作,也就是说我们提交创建任务后,若语法正确,StarRocks虽然会立刻给出反馈,但会在后台对存量的数据进行计算,直到创建成功。

还以table11为例,我们再创建一个物化视图table11_mv2:
CREATE MATERIALIZED VIEW table11_mv2 AS
SELECT seller_id, SUM(sale_amt)
FROM table11
GROUP BY seller_id;

查看创建进度(starrocks为当前的数据库名):
SHOW ALTER MATERIALIZED VIEW FROM starrocks;
当对应IndexName物化视图的State为FINISHED时,即为创建完成。

查看Base表table11的物化视图表信息,语句为:
desc table11 all;

查看starrocks库下面所有的物化视图:
SHOW MATERIALIZED VIEW IN starrocks;(这里可以用INFROM)

删除创建完成的物化视图table11_mv2(异步,但用户感知不到):
DROP MATERIALIZED VIEW IF EXISTS starrocks.table11_mv2;

由于是异步操作,若我们需要删除创建中的物化视图,可以取消其异步的创建任务,以表table11上的物化视图table11_mv1为例,取消正在创建的任务:
CANCEL ALTER MATERIALIZED VIEW FROM starrocks.table11;
执行后再次使用上面的show语句查看,当State为CANCELLED即代表已取消。

1.2 物化视图的智能路由

StarRocks中,查询时不需要显式指定MV表名称,StarRocks会根据查询SQL智能路由到最佳的MV表。在查询时,MV表的选择规则如下:

  1. 选择包含所有查询列的MV表
  2. 按照过滤和排序的Column筛选最符合的MV表
  3. 按照Join的Column筛选最符合的MV表
  4. 行数最小的MV表
  5. 列数最小的MV表

1.3 注意事项

  1. 当前物化视图只支持对单个表的聚合。目前支持的聚合函数有:COUNT、MAX、MIN、SUM、HLL_UNION和BITMAP_UNION。物化视图的聚合函数的参数仅支持单列,比如:sum(a+b)也是不支持的。
  2. 目前物化视图主要应用于明细模型,实现固定维度数据的预聚合。对于聚合模型,从预聚合的角度来讲没有创建物化视图的意义,但我们可以使用物化视图来实现更少数据量的扫描,或者通过物化视图调整列顺序以命中前缀索引(明细模型也适用)。
    • 比如创建这样的物化视图:mysql> CREATE MATERIALIZED VIEW table03_mv1 AS SELECT state, sum(pv) FROM table03 GROUP BY state;,该物化视图表只包含两列:state和sum(pv)。此时的索引前缀就变成只有一个state了,可以满足SELECT state ,sum(pv) FROM table03 GROUP BY state;这样的sql了。
  3. 如果删除语句的条件列,在物化视图中不存在,则不能进行删除操作。如果一定要删除数据,则需要先将物化视图删除,然后方可删除数据。
  4. 单表上过多的物化视图会影响导入的效率。导入数据时,物化视图和Base表数据是同步更新的,如果一张表的物化视图表超过10张,则有可能导致导入速度很慢,此时就像在同时导入10张表的数据一样。
  5. 相同列,不同聚合函数,不能同时出现在一张物化视图中,比如:select sum(a), min(a) from table不支持。
  6. 同一张表不能同时创建多个物化视图,只能等待上一个物化视图创建完成(State为FlNISHED),才能创建下一个物化视图。
  7. 物化视图的创建语句目前不支持JOIN和WHERE,也不支持GROUP BY的 HAVING子句。
  8. 在对空表查询时可能无法命中物化视图(启用CBO优化器后可以,开启方式:set global enable_cbo = true;)。
  9. 删除Base表时,所有基于Base表的物化视图会被同步删除。
  10. 主键模型目前还不支持创建物化视图(指文章更新时的2.0版本)

2. Colocation Join

在Colocation Join中,StarRocks引入了Colocation Group(CG)和Colocation Group Schema(CGS)的概念,CGS是指CG的分桶键,分桶数以及副本数等信息。Colocation Join实现的核心就是将同一个Colocation Group中的表采用一致的CGS也即使用一致的分桶键(字段数量、顺序及字段类型一致即可,名称不需要一致)、一致的副本数量和一致副本放置方式,进而保证这些Table对应的分桶副本会落在相同一组BE节点上。这样如果join列为分桶键,则计算节点只需做本地join,而无需从其他节点获取数据,进而实现大表join的加速。个人感觉就是spark或hive中的MapJoin。

2.1 创建

在建表时,我们在PROPERTIES中指定属性"colocate_with" = "group_name",即表示这个表是一个Colocation Join表,并且归属于一个指定的Colocation Group。

如果指定的Group不存在,则StarRocks会自动创建一个只包含当前这张表的Group。如果Group已存在,则StarRocks会检查当前表是否满足Colocation Group Schema。如果满足,则会创建该表,并将该表加入Group。同时,表会根据已存在的Group中的数据分布规则创建分片和副本。Group归属于一个Database,Group的名字在一个Database内唯一。

为了使得Table能够有相同的数据分布,同一CG内的Table必须保证下列约束:

  1. 同一CG内的Table的分桶键的类型、数量和顺序完全一致(字段名称可以不一致),并且桶数一致,这样才能保证多张表的数据分片能够一一对应地进行分布控制。
  2. 同一个CG内所有表的所有分区(Partition)的副本数必须一致。如果不一致,可能出现某一个Tablet的某一个副本,在同一个BE上没有其他的表分片的副本对应。
  3. 同一个CG内所有表的分区键,分区数量可以不同。
结合上面的约束条件举例:

CREATE TABLE table12(
k1 int,
v1 int sum
)
DISTRIBUTED BY HASH(k1) BUCKETS 8
PROPERTIES(
"colocate_with" = "group1",
"replication_num" = "1"
);

CREATE TABLE table13(
uid int,
city varchar(40),
total int sum
)
DISTRIBUTED BY HASH(uid) BUCKETS 8
PROPERTIES(
"colocate_with" = "group1",
"replication_num" = "1"
);

这样当对table12与table13进行关联条件为table12.k1=table13.uid的join时,
若Colocation Join生效,理论上查询效率会非常高(此时explain sql,可以发现查询计划中的Hash Join会显示colocate: true)。

image.png

2.2 其他操作

我们同样可以通过show语句查看集群内已存在的Group信息:
SHOW PROC '/colocation_group';

对一个已经创建的表,我们也可以增加、修改或删除表的colocate_with属性。例如修改table12的Colocation Group为group2:
ALTER TABLE table12 SET ("colocate_with" = "group2");
如果该表之前没有指定过Group,则该命令检查Schema,并将该表加入到该 GroupGroup不存在则会创建)。
如果该表之前有指定其他Group,则该命令会先将该表从原有Group中移除,并加入新GroupGroup不存在则会创建)。

我们也可以将表的colocate_with属性设置为空,以删除其Colocation Group属性。比如删除table12的colocate_with属性:
ALTER TABLE table12 SET ("colocate_with" = "");
当Group中最后一张表彻底删除后,该Group也会被自动删除。
(彻底删除是指从回收站中删除。通常,一张表通过DROP TABLE命令删除后,会在回收站默认停留一天的时间后,再删除)

2.3 注意事项

  1. 当对一个具有Colocation属性的表进行增加分区(ADD PARTITION)、修改副本数时,StarRocks会检查修改是否会违反Colocation Group Schema,如果违反则会拒绝。

  2. Colocation表的副本分布需要遵循Group中指定的分布,所以在副本修复和均衡方面和普通分片有所区别,前面使用show语句查看Group信息时,我们需要关注其中的IsStable属性,当值不为true时,表示当前Group内有部分表的分片正在做修复或迁移,此时,相关表的Colocation Join将退化为普通Join,在explain join sql时提示:colocate: false, reason: group is not stable。

Colocation表的副本均衡受FE参数disable_colocate_balance控制,为保证查询效率,我们可以在查询频繁的时间临时关闭Colocation表的副本修复和副本均衡,在业务空闲时间再开启。

disable_colocate_balance:是否关闭StarRocks的自动Colocation副本均衡。默认为false,即不关闭。该参数只影响Colocation表的副本均衡,不影响普通表。

这个参数都可以动态修改,关闭自动均衡的写法为:
ADMIN SET FRONTEND CONFIG ("disable_colocate_balance" = "true");

恢复自动均衡:
ADMIN SET FRONTEND CONFIG ("disable_colocate_balance" = "false");

如果想对比使用colocation join前后的join性能,也可以从session级别暂时关闭colocation join功能,SQL写法为:
set disable_colocate_join = true;

3. Schema Change

第2.10章:StarRocks表设计--Schema Change

  • 表结构变更分类
    • sorted schema change会改变列的排序方式,需对数据进行重新排序。例如删除排序列中的一列字段重排序
    • direct schema change时无需重新排序,但是需要对数据做一次转换。例如修改列的类型在前缀索引中加一列
    • linked schema change下无需转换数据,直接完成。例如加列操作
  • 增加列
  • 删除列
  • 修改列
  • 原子替换及Create table like

4. 外部表

StarRocks 支持以外部表的形式,接入其他数据源。外部表指的是保存在其他数据源中的数据表,而 StartRocks 只保存表对应的元数据,并直接向外部表所在数据源发起查询。目前 StarRocks 已支持的第三方数据源包括 MySQL、ElasticSearch、Hive以及StarRocks。对于StarRocks数据源,现阶段只支持Insert写入,不支持读取,对于其他数据源,现阶段只支持读取,还不支持写入。

第2.11章:StarRocks表设计--外部表 下面仅介绍常用的MySQL外部表,ElasticSearch、Hive以及StarRocks请查看该博客文章。

4.1 MySQL外部表

在星型模型中,我们一般将表类型划分为维度表和指标表。维度表数据量通常较小,但一般都会涉及UPDATE操作。由于当前StarRocks还未直接支持UPDATE语法,所以在某些情况下我们可以将维度表放在MySQL中,在StarRocks中为其创建外部表,然后进行关联查询(若希望最佳的查询效果,也可以将MySQL中的数据通过flink-cdc或者cannel同步至StarRocks中)。

mysql_table的建表语句为:
CREATE TABLE test.`mysql_table` (
  `id` INT(11) NOT NULL,
  `name` VARCHAR(3) DEFAULT NULL,
  `height` INT(8) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

插入数据:
insert into mysql_table values(10001,'诺亚',55),(10002,'雷杰多',50),(10003,'赛迦',58);

在StarRocks中创建外部表,这里注意,在所有外部表建表语句中,varchar的长度没有意义,只需要保证与源表中的类型对的上即可:
CREATE EXTERNAL TABLE mysql_external_table
(
    id INT,
    name VARCHAR(3),
    height INT
)
ENGINE=mysql
PROPERTIES
(
    "host" = "192.168.110.98",
    "port" = "3306",
    "user" = "root",
    "password" = "root",
    "database" = "test",
    "table" = "mysql_table"
);

查询:
mysql> select * from mysql_external_table;
+----------+-------------------+----------+
| id          | name              | height  |
+----------+-------------------+----------+
| 10001   | 诺亚                |    55     |
| 10002   | 雷杰多            |    50     |
| 10003   | 赛迦                |    58     |
+----------+-------------------+----------+