最佳实践

1 建表

1.1 数据模型选择

Doris 数据模型上目前分为三类: AGGREGATE KEY, UNIQUE KEY, DUPLICATE KEY。三种模型中数据都是按KEY进行排序。

  1. AGGREGATE KEY

    AGGREGATE KEY相同时,新旧记录进行聚合,目前支持的聚合函数有SUM, MIN, MAX, REPLACE。

    AGGREGATE KEY模型可以提前聚合数据, 适合报表和多维分析业务。

    1. CREATE TABLE site_visit
    2. (
    3. siteid INT,
    4. city SMALLINT,
    5. username VARCHAR(32),
    6. pv BIGINT SUM DEFAULT '0'
    7. )
    8. AGGREGATE KEY(siteid, city, username)
    9. DISTRIBUTED BY HASH(siteid) BUCKETS 10;
  2. UNIQUE KEY

    UNIQUE KEY 相同时,新记录覆盖旧记录。目前 UNIQUE KEY 实现上和 AGGREGATE KEY 的 REPLACE 聚合方法一样,二者本质上相同。适用于有更新需求的分析业务。

    1. CREATE TABLE sales_order
    2. (
    3. orderid BIGINT,
    4. status TINYINT,
    5. username VARCHAR(32),
    6. amount BIGINT DEFAULT '0'
    7. )
    8. UNIQUE KEY(orderid)
    9. DISTRIBUTED BY HASH(orderid) BUCKETS 10;
  3. DUPLICATE KEY

    只指定排序列,相同的行不会合并。适用于数据无需提前聚合的分析业务。

    1. CREATE TABLE session_data
    2. (
    3. visitorid SMALLINT,
    4. sessionid BIGINT,
    5. visittime DATETIME,
    6. city CHAR(20),
    7. province CHAR(20),
    8. ip varchar(32),
    9. brower CHAR(20),
    10. url VARCHAR(1024)
    11. )
    12. DUPLICATE KEY(visitorid, sessionid)
    13. DISTRIBUTED BY HASH(sessionid, visitorid) BUCKETS 10;

1.2 大宽表与 Star Schema

业务方建表时, 为了和前端业务适配, 往往不对维度信息和指标信息加以区分, 而将 Schema 定义成大宽表。对于 Doris 而言, 这类大宽表往往性能不尽如人意:

  • Schema 中字段数比较多, 聚合模型中可能 key 列比较多, 导入过程中需要排序的列会增加。
  • 维度信息更新会反应到整张表中,而更新的频率直接影响查询的效率。

使用过程中,建议用户尽量使用 Star Schema 区分维度表和指标表。频繁更新的维度表也可以放在 MySQL 外部表中。而如果只有少量更新, 可以直接放在 Doris 中。在 Doris 中存储维度表时,可对维度表设置更多的副本,提升 Join 的性能。

1.4 分区和分桶

Doris 支持两级分区存储, 第一层为 RANGE 分区(partition), 第二层为 HASH 分桶(bucket)。

  1. RANGE分区(partition)

    RANGE分区用于将数据划分成不同区间, 逻辑上可以理解为将原始表划分成了多个子表。业务上,多数用户会选择采用按时间进行partition, 让时间进行partition有以下好处:

    • 可区分冷热数据
    • 可用上Doris分级存储(SSD + SATA)的功能
    • 按分区删除数据时,更加迅速
  2. HASH分桶(bucket)

    根据hash值将数据划分成不同的 bucket。

    • 建议采用区分度大的列做分桶, 避免出现数据倾斜
    • 为方便数据恢复, 建议单个 bucket 的 size 不要太大, 保持在 10GB 以内, 所以建表或增加 partition 时请合理考虑 bucket 数目, 其中不同 partition 可指定不同的 buckets 数。

1.5 稀疏索引和 Bloom Filter

Doris对数据进行有序存储, 在数据有序的基础上为其建立稀疏索引,索引粒度为 block(1024行)。

稀疏索引选取 schema 中固定长度的前缀作为索引内容, 目前 Doris 选取 36 个字节的前缀作为索引。

  • 建表时建议将查询中常见的过滤字段放在 Schema 的前面, 区分度越大,频次越高的查询字段越往前放。
  • 这其中有一个特殊的地方,就是 varchar 类型的字段。varchar 类型字段只能作为稀疏索引的最后一个字段。索引会在 varchar 处截断, 因此 varchar 如果出现在前面,可能索引的长度可能不足 36 个字节。具体可以参阅 数据模型、ROLLUP 及前缀索引
  • 除稀疏索引之外, Doris还提供bloomfilter索引, bloomfilter索引对区分度比较大的列过滤效果明显。 如果考虑到varchar不能放在稀疏索引中, 可以建立bloomfilter索引。

1.6 物化视图(rollup)

Rollup 本质上可以理解为原始表(Base Table)的一个物化索引。建立 Rollup 时可只选取 Base Table 中的部分列作为 Schema。Schema 中的字段顺序也可与 Base Table 不同。

下列情形可以考虑建立 Rollup:

  1. Base Table 中数据聚合度不高。

这一般是因 Base Table 有区分度比较大的字段而导致。此时可以考虑选取部分列,建立 Rollup。

如对于 site_visit 表:

  1. site_visit(siteid, city, username, pv)

siteid 可能导致数据聚合度不高,如果业务方经常根据城市统计pv需求,可以建立一个只有 city, pv 的 Rollup:

  1. ALTER TABLE site_visit ADD ROLLUP rollup_city(city, pv);
  1. Base Table 中的前缀索引无法命中

这一般是 Base Table 的建表方式无法覆盖所有的查询模式。此时可以考虑调整列顺序,建立 Rollup。

如对于 session_data 表:

  1. session_data(visitorid, sessionid, visittime, city, province, ip, brower, url)

如果除了通过 visitorid 分析访问情况外,还有通过 brower, province 分析的情形,可以单独建立 Rollup。

  1. ALTER TABLE session_data ADD ROLLUP rollup_brower(brower,province,ip,url) DUPLICATE KEY(brower,province);

2 Schema Change

Doris中目前进行 Schema Change 的方式有三种:Sorted Schema Change,Direct Schema Change, Linked Schema Change。

  1. Sorted Schema Change

    改变了列的排序方式,需对数据进行重新排序。例如删除排序列中的一列, 字段重排序。

    1. ALTER TABLE site_visit DROP COLUMN city;
  2. Direct Schema Change: 无需重新排序,但是需要对数据做一次转换。例如修改列的类型,在稀疏索引中加一列等。

    1. ALTER TABLE site_visit MODIFY COLUMN username varchar(64);
  3. Linked Schema Change: 无需转换数据,直接完成。例如加列操作。

    1. ALTER TABLE site_visit ADD COLUMN click bigint SUM default '0';

建表时建议考虑好 Schema,这样在进行 Schema Change 时可以加快速度。