索引

建立索引的方法

在 Doris 中,建立索引通常是在创建表或修改表时进行的。以下是如何在创建表时添加索引的基本语法:

CREATE TABLE example_db.table_name (
    `column1` DataType1,
    `column2` DataType2,
    ...
    INDEX index_name (column_list)
) ENGINE=OLAP
DUPLICATE KEY(`column1`, `column2`)
...

或者,如果表已经存在,可以使用 ALTER TABLE 语句添加索引:

ALTER TABLE example_db.table_name ADD INDEX index_name (column_list);

索引的种类

  1. 前缀索引(Prefix Index)

    • 前缀索引是对字符串列的前几个字符建立的索引。这种索引适用于列值是长字符串,但查询时通常只需要匹配前几个字符的场景。

    • 在创建表时指定前缀索引的长度:

      CREATE TABLE example_db.table_name (
          `column1` VARCHAR(50) WITH PRECISION 10,
          ...
      ) ENGINE=OLAP
      ...
    • 这里的 WITH PRECISION 10 表示对 column1 的前10个字符建立索引。

  2. Bitmap 索引

    • Bitmap 索引适用于那些具有离散值的列,特别是那些取值有限的列,如性别、国家代码等。

    • Bitmap 索引可以显著减少数据存储空间,并提高查询效率,特别是在进行等值查询和范围查询时。

    • 创建 Bitmap 索引:

      CREATE TABLE example_db.table_name (
          `column1` INT,
          ...
      ) ENGINE=OLAP
      UNIQUE KEY(`column1`)
      PROPERTIES (
          "index_type" = "BITMAP"
      );
  3. BloomFilter 索引

    • BloomFilter 索引是一种概率型数据结构,用于判断一个元素是否在一个集合中。

    • 它可以用来加速“不等于”查询,减少回表操作,提高查询性能。

    • 创建 BloomFilter 索引:

      CREATE TABLE example_db.table_name (
          `column1` INT,
          ...
      ) ENGINE=OLAP
      UNIQUE KEY(`column1`)
      PROPERTIES (
          "bloom_filter_columns" = "column1"
      );
  4. ZORDER 索引

    • ZORDER 索引是一种多列联合索引,它将多列的值编码为一个单一的数值,用于多维数据的排序和查询。

    • 这种索引适合于需要对多个维度进行排序的场景,如地理空间数据。

    • 创建 ZORDER 索引:

      CREATE TABLE example_db.table_name (
          `column1` INT,
          `column2` INT,
          ...
      ) ENGINE=OLAP
      UNIQUE KEY(`column1`, `column2`)
      PROPERTIES (
          "index_type" = "ZORDER"
      );

分区分桶

参考链接:基本概念 - Apache Doris

分区(Partition)

分区是将表中的数据分割成多个部分,每个部分包含原始表的一个子集。在 Doris 中,分区可以基于不同策略,如范围(Range)或列表(List)。分区的主要目的是:

  1. 数据隔离:将数据逻辑上隔离,便于管理。

  2. 优化查询:查询时可以只扫描相关分区,减少数据扫描范围。

  3. 数据维护:方便对特定分区进行维护操作,如删除旧数据。

在 Doris 中创建分区表的示例:

CREATE TABLE example_db.table_name (
    `column1` DataType1,
    `column2` DataType2,
    ...
) ENGINE=OLAP
PARTITION BY RANGE(`column1`) (
    PARTITION p1 VALUES LESS THAN ('value1'),
    PARTITION p2 VALUES LESS THAN ('value2'),
    ...
);

分桶(Bucket)

分桶是将数据在物理上进一步细分为多个桶(Bucket),每个桶包含多行数据。Doris 使用哈希分桶来分布数据,以确保数据均匀分布在不同的桶中。分桶的主要目的是:

  1. 数据均匀分布:通过哈希分桶保证数据均匀分布,避免数据倾斜。

  2. 并行处理:查询时可以并行处理不同桶中的数据,提高查询效率。

  3. 数据局部性:相关数据更有可能被存储在同一个桶中,提高缓存命中率。

在 Doris 中创建分桶表的示例:

CREATE TABLE example_db.table_name (
    `column1` DataType1,
    `column2` DataType2,
    ...
) ENGINE=OLAP
DUPLICATE KEY(`column1`)
DISTRIBUTED BY HASH(`column1`) BUCKETS 16;

在这个例子中,column1 是分桶的依据,表被分为 16 个桶。

分区和分桶的结合使用

在 Doris 中,分区和分桶可以结合使用,以实现更细粒度的数据管理和优化。数据首先根据分区条件被分配到不同的分区,然后在每个分区内进一步被分桶。

CREATE TABLE example_db.table_name (
    `column1` DataType1,
    `column2` DataType2,
    ...
) ENGINE=OLAP
PARTITION BY RANGE(`column1`) (
    PARTITION p1 VALUES LESS THAN ('value1'),
    PARTITION p2 VALUES LESS THAN ('value2'),
    ...
)
DISTRIBUTED BY HASH(`column2`) BUCKETS 16;

在这个例子中,数据首先根据 column1 的值被分配到不同的分区,然后在每个分区内根据 column2 的值被进一步分桶。

与 MySQL 相比

Apache Doris 和 MySQL 在分区分桶方面有一些相似的概念,但在实现和使用上有所不同。以下是两者在分区分桶方面的对比:

分区(Partition)

MySQL:

  • MySQL 支持范围分区(RANGE)和列表分区(LIST),允许用户根据某个列的值将数据划分到不同的分区。

  • 分区可以在创建表时定义,也可以后续通过 ALTER TABLE 语句添加。

  • MySQL 的分区表在逻辑上仍然是一个单一的表,但物理上数据被存储在不同的分区中。

Doris:

  • Doris 同样支持范围分区(RANGE)和列表分区(LIST),但实现方式和使用场景更倾向于大规模数据集的OLAP查询。

  • 分区在Doris中是数据分布和存储的重要组成部分,它允许Doris在查询时只扫描相关的分区,提高查询效率。

分桶(Bucket)

MySQL:

  • MySQL 8.0 引入了虚拟列的概念,允许用户基于虚拟列的值进行分桶,这类似于Doris的分桶概念。

  • MySQL的分桶不是基于物理分布,而是逻辑上的分组,它不直接影响数据的物理存储。

Doris:

  • Doris 的分桶是基于物理分布的,它使用哈希分桶来确保数据均匀分布在不同的桶(Bucket)中。

  • 分桶是Doris数据模型的一部分,可以在创建表时定义,并且直接影响数据的物理存储和查询性能。

相似之处:

  • 两者都允许用户通过分区来优化查询性能,减少数据扫描的范围。

  • 两者都支持基于列值的逻辑分区。

不同之处:

  • MySQL 的分区更多地用于简化数据管理,如归档旧数据,而Doris的分区更侧重于提高查询性能。

  • Doris 的分桶是物理分布的,直接影响数据的存储和查询,而MySQL的分桶(虚拟列)更多是逻辑上的分组。

  • Doris 的分桶数量和策略在创建表时定义,并且与数据模型(如 Aggregate、Unique、Duplicate)紧密相关,而MySQL的分桶策略更灵活,可以在查询时动态指定。