行列混存

更新时间:
复制为 MD 格式

SelectDB支持行列混存模式,在列式存储的基础上额外存储行格式数据,有效解决高并发点查场景下的I/O放大问题,显著提升点查性能。

行列混存介绍

SelectDB默认采用列式存储,列存在大规模分析查询(如聚合、过滤)场景下具有明显优势。但在高并发点查场景(即按主键精确查询少量行),列存需要逐列读取数据并进行Merge,会引发大量随机I/O,导致性能下降。

行列混存通过在列存数据之外,额外维护一份行格式的数据副本,使得点查时可以直接从行存中读取完整的行数据,避免多列的随机I/O,从而大幅提升高并发点查的性能。

行列混存适用于以下场景:

  • 基于主键的高并发点查(如订单详情查询、用户信息查询)

  • 需要返回行内全部或大部分列的SELECT *查询

重要

启用行列混存后,存储空间会增加约24倍(具体取决于列数和数据特征)。建议仅在有高并发点查需求的表上启用该功能,以平衡性能与存储成本。

使用语法

CREATE TABLE语句的PROPERTIES中配置以下参数来启用行列混存:

参数

说明

默认值

store_row_column

是否开启行存。设置为true后,将为表的所有列存储行格式数据。

false

row_store_columns

指定需要存储行格式的列名列表(英文逗号分隔)。当store_row_columntrue时,默认所有列开启行存;如果只需部分列开启行存,可通过此参数指定,以节省存储空间。

空(不指定则存储所有列)

row_store_page_size

行存数据页(Page)的大小(字节)。Page是存储读写的最小单元,读取一行至少产生一个PageI/O。值越小点查性能越好但存储空间越大,值越大存储空间越小但点查I/O开销越大。如果更偏向点查性能可配置较小值(如40964 KB),如果更偏向节省存储空间可配置较大值(如6553664 KB)。

16384(16 KB)

行存命中条件

启用行列混存后,行存命中分为以下两种情况:

主键高并发点查

需要同时满足以下条件:

  • 表为Unique Key模型(MOW表),即建表时设置了enable_unique_key_merge_on_write = true

  • 已开启行存(store_row_column = true或设置了row_store_columns)。

  • 查询的WHERE条件包含所有主键列的等值条件,且条件之间用AND连接。例如SELECT * FROM tbl WHERE k1 = 1 AND k2 = 2

如果行存只包含部分列(通过row_store_columns指定),但查询的列不在行存中,则这些列会从列存中查询。通过EXPLAIN查看是否包含SHORT-CIRCUIT标记来确认是否命中主键高并发点查优化。更多详情请参考高并发点查

一般的SELECT *查询

需要同时满足以下条件:

  • 表模型为Duplicate KeyUnique Key(MOW表)。

  • 已开启全列行存(store_row_column = true)。

  • 查询必须是SELECT *,且需要命中TOPN的延迟物化优化(查询包含ORDER BYLIMIT子句)。

示例:

SELECT * FROM tbl WHERE k < 10 ORDER BY k LIMIT 10;

通过EXPLAIN查看是否包含FETCH ROW STOREOPT TWO PHASE标记来确认是否命中行存。

对于分析型查询(如聚合、范围扫描),系统仍会使用列存路径,以保证最佳的分析性能。

使用示例

说明

行存配置在建表时指定,建表后不支持修改。

开启全列行存

对表的所有列开启行存,适合SELECT *类高并发点查场景:

CREATE TABLE user_profile (
    user_id BIGINT,
    user_name VARCHAR(64),
    age INT,
    city VARCHAR(32),
    register_date DATE
)
UNIQUE KEY(user_id)
DISTRIBUTED BY HASH(user_id) BUCKETS 16
PROPERTIES (
    "store_row_column" = "true",
    "enable_unique_key_merge_on_write" = "true"
);

开启部分列行存

仅对查询中常用的部分列开启行存,可以在节省存储空间的同时提升点查性能:

CREATE TABLE order_info (
    order_id BIGINT,
    user_id BIGINT,
    amount DECIMAL(12, 2),
    status INT,
    create_time DATETIME,
    detail VARCHAR(1024)
)
UNIQUE KEY(order_id)
DISTRIBUTED BY HASH(order_id) BUCKETS 32
PROPERTIES (
    "row_store_columns" = "user_id,amount,status,create_time",
    "enable_unique_key_merge_on_write" = "true"
);

调整行存Page大小

对于行宽较大(列多或字段较长)的表,可适当增大row_store_page_size以减少Page数量,提升读取效率:

CREATE TABLE wide_table (
    id BIGINT,
    col1 VARCHAR(256),
    col2 VARCHAR(256),
    col3 VARCHAR(256)
)
UNIQUE KEY(id)
DISTRIBUTED BY HASH(id) BUCKETS 8
PROPERTIES (
    "store_row_column" = "true",
    "row_store_page_size" = "65536",
    "enable_unique_key_merge_on_write" = "true"
);

注意事项

  • 开启行存后存储空间会增加,典型场景下约为原始表的24倍,具体空间占用需使用实际数据测试。

  • row_store_page_size对存储空间也有影响,建议根据业务场景在点查性能和存储空间之间权衡。

  • 如果仅部分列需要行存,建议使用row_store_columns指定具体列,可有效减少额外存储开销。

  • 行存配置在建表时指定,建表后不支持修改。