SelectDB支持行列混存模式,在列式存储的基础上额外存储行格式数据,有效解决高并发点查场景下的I/O放大问题,显著提升点查性能。
行列混存介绍
SelectDB默认采用列式存储,列存在大规模分析查询(如聚合、过滤)场景下具有明显优势。但在高并发点查场景(即按主键精确查询少量行),列存需要逐列读取数据并进行Merge,会引发大量随机I/O,导致性能下降。
行列混存通过在列存数据之外,额外维护一份行格式的数据副本,使得点查时可以直接从行存中读取完整的行数据,避免多列的随机I/O,从而大幅提升高并发点查的性能。
行列混存适用于以下场景:
基于主键的高并发点查(如订单详情查询、用户信息查询)
需要返回行内全部或大部分列的
SELECT *查询
启用行列混存后,存储空间会增加约2到4倍(具体取决于列数和数据特征)。建议仅在有高并发点查需求的表上启用该功能,以平衡性能与存储成本。
使用语法
在CREATE TABLE语句的PROPERTIES中配置以下参数来启用行列混存:
参数 | 说明 | 默认值 |
| 是否开启行存。设置为 |
|
| 指定需要存储行格式的列名列表(英文逗号分隔)。当 | 空(不指定则存储所有列) |
| 行存数据页(Page)的大小(字节)。Page是存储读写的最小单元,读取一行至少产生一个Page的I/O。值越小点查性能越好但存储空间越大,值越大存储空间越小但点查I/O开销越大。如果更偏向点查性能可配置较小值(如4096即4 KB),如果更偏向节省存储空间可配置较大值(如65536即64 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 Key或Unique Key(MOW表)。
已开启全列行存(
store_row_column = true)。查询必须是
SELECT *,且需要命中TOPN的延迟物化优化(查询包含ORDER BY和LIMIT子句)。
示例:
SELECT * FROM tbl WHERE k < 10 ORDER BY k LIMIT 10;通过EXPLAIN查看是否包含FETCH ROW STORE和OPT 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"
);注意事项
开启行存后存储空间会增加,典型场景下约为原始表的2到4倍,具体空间占用需使用实际数据测试。
row_store_page_size对存储空间也有影响,建议根据业务场景在点查性能和存储空间之间权衡。如果仅部分列需要行存,建议使用
row_store_columns指定具体列,可有效减少额外存储开销。行存配置在建表时指定,建表后不支持修改。