Hologres索引入门

本文为您介绍Hologres中的关键索引,如Distribution Key、Event Time Column(Segment Key)和Clustering Key,帮助您在Hologres开发过程中快速上手使用索引,提升查询性能。

分布式数据仓库Hologres基本运行原理

Hologres是一个分布式数据仓库,采用并行计算和向量计算技术实现秒级查询响应,因此数据的分布特征对性能有关键影响,包括数据在多个分布式节点间的分布均衡性(distribution_key),以及单个节点内文件之间的分布有序性(event_time_column/segment_key)。同时Hologres在OLAP场景默认使用列存储格式,因此数据在文件内的有序性(clustering_key)也至关重要。掌握这三个概念,在性能优化时可以事半功倍。由于数据分布特征是在数据写入时确定,调整成本高,因此建议在建表时,设计与数据布局相关的三个属性。而与数据布局无直接关联的属性,如位图索引(bitmap_columns),字典编码(dictionary_columns)等,可以在建表之后,按需调整。

同时Hologres的元数据采用三级结构Database>Schema>Table,建议逻辑相关的表内聚在Schema下,避免跨库查询。Database是元数据隔离的基本单位,不是资源隔离的单位。

SQL优化的基本原理:减少IO,优化并发

建表时设计合适的数据分布,能够使SQL在执行时快速命中数据,减少IO消耗,以更少的计算资源,实现更高的查询性能,同时均衡的数据分布也使得并发资源可以充分发挥,避免单点瓶颈。下图是一个SQL从发起到获取数据的执行流程,可以通过下图理解减少IO的流程。image

  • 分区剪枝(Partition Pruning):SQL执行时,对于目标分区表,会通过分区裁剪,定位到所在分区。如果查询条件和分区不匹配,需要遍历所有分区,会引起过多的IO扫描,通常分区选择日粒度比较合适。对于非分区表直接略过,不进行分区裁剪。

  • 分片剪枝(Shard Pruning):通过分布键(distribution_key)快速定位到数据所在的数据分片,可以减少单个SQL执行时的资源消耗,对于并发SQL,满足更高的吞吐能力;如果无法定位到某个分片,会通过分布式框架调度所有的分片参与计算,单个SQL的并行度更高,资源使用更多,但并发能力会降低,部分需要集中化执行的算子会带来额外的Shuffle开销。通常分布键选择订单ID、用户ID、事件ID等分布比较均衡的字段,多个需要JOIN的表使用相同的分布键,可以使相关的数据分片到同一个Shard,通过Local JOIN实现更高的JOIN效率。

  • 文件剪枝(Segment Key Pruning):通过分段键(event_time_column/segment_key),快速定位到单个节点内部多个文件中的数据所在文件位置,避免打开不需要访问的文件。如果无法过滤,则需要遍历所有的文件。

  • 聚簇剪枝(Clustering Key Pruning):通过聚簇键(clustering_key),快速定位单个文件内部的数据段,提高范围查询和字段排序的效率。

SQL优化实践

此处以TPC-H的部分Query为例,为您介绍如何设置Hologres的索引,以获得更好的查询性能。关于TPC-H的详细介绍,请参见测试方案介绍

TPCH SQL参考实践

TPC-H Q1 Query

TPC-H Q1主要是对lineitem表的部分字段做聚合查询和过滤筛选。其中:

l_shipdate <= :过滤查询。需要设置索引以支持范围过滤,可快速过滤出所需数据。

--TPC-H Q1
SELECT
        l_returnflag,
        l_linestatus,
        SUM(l_quantity) AS sum_qty,
        SUM(l_extendedprice) AS sum_base_price,
        SUM(l_extendedprice * (1 - l_discount)) AS sum_disc_price,
        SUM(l_extendedprice * (1 - l_discount) * (1 + l_tax)) AS sum_charge,
        AVG(l_quantity) AS avg_qty,
        AVG(l_extendedprice) AS avg_price,
        AVG(l_discount) AS avg_disc,
        COUNT(*) AS count_order
FROM
        lineitem
WHERE
        l_shipdate <= DATE '1998-12-01' - INTERVAL '120' DAY
GROUP BY
        l_returnflag,
        l_linestatus
ORDER BY
        l_returnflag,
        l_linestatus;

TPC-H Q4 Query

TPC-H Q4主要是对lineitem和orders表进行关联查询。其中:

  • o_orderdate >= DATE '1996-07-01':过滤查询。需要设置索引以支持范围过滤,可快速过滤出所需数据。

  • l_orderkey = o_orderkey:两表JOIN。需要为两个表设置同一个索引,最好能进行Local JOIN,以减少数据在两表交互时的Shuffle操作。

    --TPC-H Q4 Query
    SELECT
            o_orderpriority,
            COUNT(*) AS order_count
    FROM
            orders
    WHERE
            o_orderdate >= DATE '1996-07-01'
            AND o_orderdate < DATE '1996-07-01' + INTERVAL '3' MONTH
            AND EXISTS (
                    SELECT
                            *
                    FROM
                            lineitem
                    WHERE
                            l_orderkey = o_orderkey
                            AND l_commitdate < l_receiptdate
            )
    GROUP BY
            o_orderpriority
    ORDER BY
            o_orderpriority;

建表建议

在上述的Q1和Q4查询中,主要涉及lineitem和orders两张表,分别如下:

hologres_dataset_tpch_100g.lineitem

Q1和Q4中均涉及对lineitem表的查询,其中使用的字段和查询条件不同。

  • 对于Q1 Query:主要用l_shipdate做范围过滤筛选。clustering_key可以利用文件内的有序性加速范围过滤,因此我们可将l_shipdate设置为Clustering Key。segment_key(event_time_column)用于保持文件间的有序性,对于单调递增/递减的日期字段,也建议设置为Segment Key,可以有效进行文件层过滤,因此也可将l_shipdate设置为Segment Key

  • 对于Q4 Query :主要用lineitem表的l_orderkey字段与orders表的o_orderkey字段进行关联查询(JOIN)。distribution_key用于指定数据的分布策略,系统会根据distribution_key,将相同的数据存放在同一个Shard上,当两张表在同一个Table Group内,并且JOIN的字段是Distribution Key时,在进行数据写入时,会自动将两张表重相同Key的记录分发到同一个Shard上,当表进行JOIN时,只需要在当前节点进行Local JOIN,无需按照JOIN Key进行数据Shuffle,避免了运行时数据打散和重分发,可以显著提高执行效率。因此,我们将l_orderkey设置为Distribution Key。

  • 最终lineitem表的表结构如下:

    BEGIN;
    CREATE TABLE hologres_dataset_tpch_100g.lineitem
    (
        l_ORDERKEY      BIGINT      NOT NULL,
        L_PARTKEY       INT         NOT NULL,
        L_SUPPKEY       INT         NOT NULL,
        L_LINENUMBER    INT         NOT NULL,
        L_QUANTITY      DECIMAL(15,2) NOT NULL,
        L_EXTENDEDPRICE DECIMAL(15,2) NOT NULL,
        L_DISCOUNT      DECIMAL(15,2) NOT NULL,
        L_TAX           DECIMAL(15,2) NOT NULL,
        L_RETURNFLAG    TEXT        NOT NULL,
        L_LINESTATUS    TEXT        NOT NULL,
        L_SHIPDATE      TIMESTAMPTZ NOT NULL,
        L_COMMITDATE    TIMESTAMPTZ NOT NULL,
        L_RECEIPTDATE   TIMESTAMPTZ NOT NULL,
        L_SHIPINSTRUCT  TEXT        NOT NULL,
        L_SHIPMODE      TEXT        NOT NULL,
        L_COMMENT       TEXT        NOT NULL,
        PRIMARY KEY (L_ORDERKEY,L_LINENUMBER)
    )
    WITH (
        distribution_key = 'L_ORDERKEY',--在join时可以实现local join
        clustering_key = 'L_SHIPDATE',--加速范围过滤
        event_time_column = 'L_SHIPDATE'--加速文件裁剪
      );
    COMMIT;

hologres_dataset_tpch_100g.orders

本示例中,orders表参与Q4 Query的计算。

  • 将orders表的o_orderkey字段设置为Distribution Key,可有效利用Local JOIN的能力,提升关联(JOIN)查询的效率。

  • o_orderdate字段主要用于日期字段的过滤查询,所以将其设置为Segment Key,加速文件的裁剪。

  • 最终orders表的表结构如下:

    BEGIN;
    CREATE TABLE hologres_dataset_tpch_100g.orders
    (
        O_ORDERKEY      BIGINT      NOT NULL PRIMARY KEY,
        O_CUSTKEY       INT         NOT NULL,
        O_ORDERSTATUS   TEXT        NOT NULL,
        O_TOTALPRICE    DECIMAL(15,2) NOT NULL,
        O_ORDERDATE     timestamptz NOT NULL,
        O_ORDERPRIORITY TEXT        NOT NULL,
        O_CLERK         TEXT        NOT NULL,
        O_SHIPPRIORITY  INT         NOT NULL,
        O_COMMENT       TEXT        NOT NULL
    )
    WITH (
        distribution_key = 'O_ORDERKEY',--在join时可以实现local join
        event_time_column = 'O_ORDERDATE'--加速文件裁剪
      );
    COMMIT;

样例数据导入

通过HoloWeb一键导入公共数据集功能,将TPC-H 100 GB的数据快速导入至Hologres实例中,详情请参见一键导入公共数据集image

性能测试结果对比

为表设置了合适的属性(索引)后,测试优化前后的性能结果。

  • 测试环境

    • 实例规格:32 Core。

    • 网络类型:VPC网络。

    • 使用PSQL客户端执行两次Query,取第二次执行的时间。

  • 测试结论

    • 对于单表的过滤查询,将过滤字段设置为Clustering Key,可以有效加速查询。

    • 对于多表关联的查询,将JOIN字段设置为Distribution Key,可以显著加速JOIN效率。

    Query

    Hologres设置索引的Latency

    Hologres未设置任何索引的Latency

    Q1

    48.293 ms

    59.483 ms

    Q4

    822.389 ms

    3027.957 ms

附录资料参考

阅读更多

技术原理篇

Hologres技术原理揭秘(架构、存储引擎、计算引擎等核心原理揭秘):阿里巴巴云原生实时数仓核心技术揭秘

服务开通篇

数据导入篇

数据查询篇

运维监控篇

实践案例篇

实践与案例集:行业典型场景最佳实践与经典用户案例