宽表引擎数据

更新时间:
复制 MD 格式

OLAP资源组支持面向宽表数据的多种查询范式,包括主键点查、非主键过滤、数据分析、全文搜索、向量检索等,并支持综合利用宽表引擎各类数据索引,实现查询自动加速。本文主要介绍访问宽表数据的多种方式。

前提条件

宽表管理

OLAP资源组支持对宽表引擎中的 Database 和 Table 进行完整的生命周期管理。

创建 Database

CREATE DATABASE <db_name>;

示例:

CREATE DATABASE mydb;

删除 Database

DROP DATABASE <db_name>;

示例:

DROP DATABASE mydb;

创建宽表

详细的建表 SQL 语法请参见 CREATE TABLE,OLAP 资源组支持其中的常用数据类型子集。

CREATE TABLE <table_name> (
  <col_name> <data_type> [NOT NULL],
  ...
  PRIMARY KEY(<pk_col1> [, <pk_col2>, ...])
);
  • 主键列须声明 NOT NULL,主键由一列或多列组成,唯一标识一行数据。

  • OLAP 资源组支持以下数据类型:

类型

说明

BOOLEAN

布尔值

TINYINT

8 位整数

SMALLINT

16 位整数

INT / INTEGER

32 位整数

BIGINT

64 位整数

FLOAT

单精度浮点

DOUBLE

双精度浮点

VARCHAR / VARCHAR(N)

变长字符串

BINARY / VARBINARY

二进制数据

示例:

USE mydb;

-- 用户行为日志表(复合主键)
CREATE TABLE user_event (
  user_id    VARCHAR NOT NULL,
  event_id   BIGINT  NOT NULL,
  event_type TINYINT,
  amount     DOUBLE,
  region     VARCHAR,
  PRIMARY KEY(user_id, event_id)
);

-- 订单表(单主键)
CREATE TABLE orders (
  order_id VARCHAR NOT NULL,
  user_id  VARCHAR,
  status   TINYINT,
  total    DOUBLE,
  PRIMARY KEY(order_id)
);

删除宽表

DROP TABLE <table_name>;

示例:

DROP TABLE orders;

数据写入

OLAP 资源组支持通过 INSERT INTO 语句向宽表引擎写入数据。宽表引擎不支持 UPDATE 和 DELETE 操作,数据更新需通过宽表引擎原生接口(如 HBase/Phoenix)进行。

写入单行

INSERT INTO <table_name> VALUES (<val1>, <val2>, ...);

批量写入

INSERT INTO <table_name> VALUES
  (<val1>, <val2>, ...),
  (<val1>, <val2>, ...),
  ...;

示例:

USE mydb;

-- 单行写入
INSERT INTO orders VALUES ('u001', 'o10001', 100.0, 'SHIPPED', 'Beijing', '2024-01-01');

-- 批量写入
INSERT INTO orders VALUES
  ('u001', 'o10002', 200.0, 'SHIPPED',   'Shanghai', '2024-01-02'),
  ('u002', 'o20001', 50.0,  'PENDING',   'Beijing',  '2024-01-03'),
  ('u002', 'o20002', 300.0, 'DELIVERED', 'Shenzhen', '2024-01-04');

索引管理

宽表引擎支持多种索引类型,OLAP 资源组可通过 SQL 创建和管理这些索引,以加速不同场景下的查询。

列存索引

列存索引(Columnar Index)将宽表数据同步到列式存储,供 OLAP 资源组高效扫描,适合大范围聚合分析场景。

CREATE INDEX <index_name>
USING COLUMNAR
ON <table_name>(*)
PARTITION BY ENUMERABLE (
    [<pk_col> [, ...],]
    bucket(<bucket_num>, <pk_col>)
)
WITH (
    `lindorm_columnar.user.index.database` = '<db_name>',
    `lindorm_columnar.user.index.table` = '<table_name>'
);

语法解释:

参数

说明

index_name

索引名称

table_name

目标宽表名称

PARTITION BY ENUMERABLE

指定索引数据的分区策略,由普通分区表达式和 bucket 分区表达式共同构成,两类表达式中的字段均须为宽表主键字段

普通分区表达式

可选,0个或多个宽表主键字段(如日期、城市等低基数字段),用逗号分隔。索引数据按不同分区值分别构建,查询时可按分区条件高效定位。不建议使用高基数字段(如用户ID)作为普通分区键,否则会产生大量小分区

bucket(<bucket_num>, <pk_col>)

必填,至少一个。bucket_num 为分桶数,pk_col 为宽表主键字段,系统对该字段计算哈希值后对 bucket_num 取余得出分桶编号。分桶字段应具备足够的离散性,避免数据倾斜

lindorm_columnar.user.index.database

列存索引数据写入的目标 Database

lindorm_columnar.user.index.table

列存索引数据写入的目标 Table

说明 普通分区表达式与 bucket 分区表达式共同决定索引的分区数量,建议每个分区的数据量控制在 50 MB ~ 512 MB 之间。例如,宽表日均数据量 50 GB、主键为 (id, dt),可配置为 PARTITION BY ENUMERABLE (dt, bucket(200, id))

示例:

-- 为 test 表创建列存索引
-- 宽表主键为 (p2, createtime),按 createtime 普通分区 + p2 哈希分桶(128个桶)
CREATE INDEX columnar_idx
USING COLUMNAR
ON test(*)
PARTITION BY ENUMERABLE (
    createtime,
    bucket(128, p2)
)
WITH (
    `lindorm_columnar.user.index.database` = 'mydb',
    `lindorm_columnar.user.index.table` = 'test'
);

二级索引

二级索引(Secondary Index)基于指定列构建独立索引结构,加速非主键列的点查和范围查询,支持覆盖列以避免回表。

CREATE INDEX <index_name>
ON <table_name>(<col_name> [ASC|DESC] [, ...])
[INCLUDE(<col_name> [, ...])];

语法解释:

参数

说明

index_name

索引名称

table_name

目标宽表名称

col_name [ASC\|DESC]

索引列及排序方向,可指定多列,查询时条件需匹配索引列前缀

INCLUDE

覆盖列,将额外列存入索引,查询时无需回表即可返回这些列的值

示例:

-- 为 test 表的 c1 列创建二级索引,覆盖 c3、c4 列以避免回表
CREATE INDEX secondary_idx ON test(c1 DESC) INCLUDE(c3, c4);

搜索索引

搜索索引(Search Index)基于倒排结构,支持全文检索(MATCH)和结构化字段的精确查询。字段类型 text 用于分词全文检索,string 用于精确匹配(支持 =LIKE 等比较操作)。

CREATE INDEX <index_name>
USING SEARCH
ON <table_name>(<col_spec> [, ...]);

语法解释:

参数

说明

index_name

索引名称

table_name

目标宽表名称

col_spec

列的索引配置,格式为 col_name(type=<field_type>[, analyzer=<analyzer>][, indexed=true]);使用 '*' 表示覆盖所有列

type

字段类型:text 用于分词全文检索,string 用于精确匹配

analyzer

分词器,仅 type=text 时有效,常用值为 ik(中文分词)、standard(英文分词)

indexed

是否对该列建立全文索引,设为 true 时支持 MATCH 检索

示例:

-- 为 test 表创建搜索索引:所有列支持结构化查询,c3 列额外启用中文分词全文检索
CREATE INDEX search_idx USING SEARCH ON test('*', c3(type=text, analyzer=ik, indexed=true));

查看索引

SHOW INDEX FROM <table_name>;

示例:

SHOW INDEX FROM test;

删除索引

DROP INDEX <index_name> ON <table_name>;

示例:

DROP INDEX search_idx ON test;

查询实践

OLAP 资源组将宽表引擎的存储能力与 MPP 分布式执行引擎深度融合,支持主键点查、非主键过滤、聚合分析、全文检索、向量召回等多种查询范式。针对不同业务场景,可在宽表上构建列存索引、二级索引或搜索索引——OLAP 资源组在查询规划阶段自动识别并利用合适的索引,在不改变查询 SQL 的前提下实现数倍至数十倍的性能加速。

主键查询

主键查询根据主键列对数据进行过滤,支持全主键等值点查、前缀主键范围扫描等访问模式。宽表引擎对主键查询进行了原生优化,可实现毫秒级定位。

-- 建表
CREATE TABLE orders (
  user_id     VARCHAR NOT NULL,
  order_id    VARCHAR NOT NULL,
  amount      DOUBLE,
  status      VARCHAR,
  region      VARCHAR,
  create_time VARCHAR,
  PRIMARY KEY(user_id, order_id)
);

-- 全主键等值点查
SELECT * FROM orders WHERE user_id = 'u001' AND order_id = 'o10001';

-- 前缀主键范围扫描
SELECT * FROM orders WHERE user_id = 'u001' AND order_id >= 'o10001';

-- 部分主键扫描
SELECT * FROM orders WHERE user_id >= 'u001';

非主键查询

非主键查询根据非主键列进行过滤。默认情况下走全表扫描;根据过滤列的查询类型,可选择创建二级索引搜索索引,OLAP 资源组自动利用索引加速查询,无需修改 SQL。

-- 建表
CREATE TABLE orders (
  user_id     VARCHAR NOT NULL,
  order_id    VARCHAR NOT NULL,
  amount      DOUBLE,
  status      VARCHAR,
  region      VARCHAR,
  create_time VARCHAR,
  PRIMARY KEY(user_id, order_id)
);

基于二级索引的非主键查询

二级索引适用于等值、范围、模糊匹配等结构化过滤场景。

-- 为 status 列创建二级索引,覆盖 amount、region,避免回表
CREATE INDEX idx_status ON orders(status) INCLUDE(amount, region);

-- 等值过滤(命中二级索引)
SELECT user_id, order_id, amount, region FROM orders WHERE status = 'SHIPPED';

-- 范围过滤(命中二级索引)
SELECT user_id, order_id, amount FROM orders WHERE status >= 'S' AND status < 'T';

-- 模糊匹配(命中二级索引)
SELECT user_id, order_id, amount, region FROM orders WHERE status LIKE 'SH%';

基于搜索索引的非主键查询

搜索索引适用于 string 类型字段的等值、精确匹配,以及 text 类型字段的分词全文检索(MATCH)。

-- 为 region 创建搜索索引(string 类型,支持等值和 LIKE)
CREATE INDEX idx_search USING SEARCH ON orders(region(type=string, indexed=true));

-- 等值过滤(命中搜索索引)
SELECT * FROM orders WHERE region = 'Beijing';

-- LIKE 过滤(命中搜索索引,string 类型支持)
SELECT * FROM orders WHERE region LIKE 'Bei%';

-- MATCH 全文检索(命中搜索索引)
SELECT * FROM orders WHERE region MATCH 'Beijing Shanghai';

全文检索

对宽表中的文本字段创建搜索索引后,可通过 MATCH 语法对普通字段和 JSON 字段进行全文检索。OLAP 资源组自动将检索条件下推至搜索索引,实现高效的倒排召回。

MATCH 表达式支持以下匹配规则:

语法

含义

word

包含该词

+word

必须包含该词

-word

不能包含该词

"phrase"

包含完整短语(不分词)

+(word1 word2)

必须包含括号内任一词

-- 建表(含文本字段和 JSON 字段)
CREATE TABLE orders (
  user_id     VARCHAR NOT NULL,
  order_id    VARCHAR NOT NULL,
  amount      DOUBLE,
  status      VARCHAR,
  region      VARCHAR,
  create_time VARCHAR,
  user_json   VARCHAR,
  PRIMARY KEY(user_id, order_id)
);

-- 为 region 创建搜索索引(string 类型,支持精确匹配和 LIKE)
-- 为 user_json 内的 address 字段启用中文分词全文检索
CREATE INDEX search_idx USING SEARCH ON orders(
  region(type=string, indexed=true),
  user_json(type=text, analyzer=ik, indexed=true)
);

-- 包含 'Beijing' 或 'Shanghai'
SELECT * FROM orders WHERE region MATCH 'Beijing Shanghai';

-- 必须包含 'Beijing',不能包含 'Shanghai'
SELECT * FROM orders WHERE region MATCH '+Beijing -Shanghai';

-- 包含完整短语 'Beijing Chaoyang'
SELECT * FROM orders WHERE region MATCH '"Beijing Chaoyang"';

-- 必须包含 'Beijing',且包含 'Chaoyang' 或 'Haidian'
SELECT * FROM orders WHERE region MATCH '+Beijing +(Chaoyang Haidian)';

-- JSON 字段包含 'Beijing'(对列直接使用 MATCH,搜索索引覆盖整列内容)
SELECT * FROM orders WHERE user_json MATCH 'Beijing';

复杂分析

OLAP 资源组支持对宽表数据进行大规模聚合、多表关联、窗口计算等复杂分析。为宽表创建列存索引后,分析查询所需的列数据将从列式存储高效读取,大幅降低 I/O,OLAP 资源组自动完成索引路由,无需修改 SQL。

-- 建表(region 作为主键前缀,便于按地区分区)
CREATE TABLE orders (
  region      VARCHAR NOT NULL,
  user_id     VARCHAR NOT NULL,
  order_id    VARCHAR NOT NULL,
  amount      DOUBLE,
  status      VARCHAR,
  create_time VARCHAR,
  PRIMARY KEY(region, user_id, order_id)
);

-- 创建列存索引,按 region 普通分区 + user_id 哈希分桶(128桶)
-- 注意:PARTITION BY ENUMERABLE 中的字段须为主键字段
CREATE INDEX columnar_idx
USING COLUMNAR
ON orders(*)
PARTITION BY ENUMERABLE (
    region,
    bucket(128, user_id)
)
WITH (
    `lindorm_columnar.user.index.database` = 'mydb',
    `lindorm_columnar.user.index.table` = 'orders'
);

-- 大范围聚合分析(命中列存索引)
SELECT
    region,
    COUNT(*)       AS order_cnt,
    SUM(amount)    AS gmv,
    AVG(amount)    AS aov
FROM orders
WHERE region IN ('Shanghai', 'Beijing')
GROUP BY region
ORDER BY gmv DESC;

-- UNION 查询
(SELECT user_id, order_id, amount, status, region FROM orders WHERE region = 'Beijing')
UNION ALL
(SELECT user_id, order_id, amount, status, region FROM orders WHERE status LIKE 'SH%');

向量检索

如果宽表引擎数据已经构建了基础特性,可通过OLAP资源组发起对该表的向量检索——基于向量相似度完成数据召回。

查询格式:

SELECT /*+ _l_force_vector_index_(${PROPERTIES}) */ ${SELECT_LIST}[,_vector_score_(${EMBEDDING_COLUMN}, ${TARGET_VECTOR})]
FROM ${TABLE_NAME}
WHERE ${CONDITION}
ORDER BY ${DISTANCE_FUNCTION}(${EMBEDDING_COLUMN}, ${TARGET_VECTOR})
LIMIT ${K}

语法说明:

  1. 变量含义:

    变量名

    变量含义

    ${SELECT_LIST}

    查询目标列。

    _vector_score_(${EMBEDDING_COLUMN}, ${TARGET_VECTOR})

    返回相似分数,其中EMBEDDING_COLUMN,和TARGET_VECTOR两个参数需要和DISTANCE_FUNCTION的参数相同。

    ${TABLE_NAME}

    目标表。

    ${CONDITION}

    标量过滤条件。

    ${DISTANCE_FUNCTION}

    相似距离函数,目前支持l2_distancecosine_similarityinnerproduct_distance

    ${EMBEDDING_COLUMN}

    构建向量索引列。

    ${TARGET_VECTOR}

    目标向量 (字符串表达的浮点数组)。

    ${PROPERTIES}

    向量检索的支持的参数,比如k=10lvector.min_score=0

  2. 距离函数:支持 l2_distancecosine_similarityinnerproduct_distance 。

  3. Hint:通过 /*+ _l_force_vector_index_(...) */ 查询向量索引和配置向量查询参数,支持的参数如下:

    参数

    是否必填

    说明

    k

    返回最相似的K个数据,请注意参数kLIMIT需要保持一致。

    lvector.min_score

    相似度阈值,要求返回的向量得分大于该值。返回的向量得分范围为[0,1]。 取值范围:[0,+inf]。默认值为0

    lvector.ef_search

    HNSW算法中,索引查询时动态列表的长度。只能用于HNSW算法。 取值范围:[1,1000]。默认值为100

    lvector.nprobe

    要查询的聚类单元(cluster units)的数量。请根据您的召回率要求,对该参数的值进行调整已达到理想效果。值越大,召回率越高,搜索性能越低。 取值范围:[1,method.parameters.nlist]。无默认值。 重要 仅适用于ivfpq算法。

    lvector.reorder_factor

    使用原始向量创建重排序(reorder)。ivfpq算法计算的距离为量化后的距离,会有一定的精度损失,需要使用原始向量进行重排序。比例为k * reorder_factor ,通常用于提升召回精度,但会增加性能开销。 取值范围:[1,200]。默认值为10。 重要 - 仅适用于ivfpq算法。 - k值较小时可以设置为5,如果k大于100,直接设置为1即可。

    lvector.client_refactor

    是否不在每个分片(Shard)内进行重排序,而是在系统上层进行重排序,进而提升系统性能。取值如下: - true:是。 - false(默认值):否。

    lvector.filter_type

    融合查询使用的模式。取值如下: - pre_filter:先过滤结构化数据,再查询向量数据。 - post_filter:先查询向量数据,再过滤结构化数据。

宽表表结构示例:

-- 已建好如下宽表,已对 item_embedding 列创建向量索引
+----------------+---------------------+------+-------+---------+---------------+---------+
| Field          | Type                | Null | Key   | Default | Extra         | Comment |
+----------------+---------------------+------+-------+---------+---------------+---------+
| user_id        | VARCHAR(1073741824) | No   | true  | NULL    | partition key |         |
| order_id       | VARCHAR(1073741824) | No   | true  | NULL    | partition key |         |
| amount         | DOUBLE              | Yes  | false | NULL    |               |         |
| status         | VARCHAR(1073741824) | Yes  | false | NULL    |               |         |
| region         | VARCHAR(1073741824) | Yes  | false | NULL    |               |         |
| create_time    | VARCHAR(1073741824) | Yes  | false | NULL    |               |         |
| item_embedding | VARCHAR(1073741824) | Yes  | false | NULL    |               |         |
+----------------+---------------------+------+-------+---------+---------------+---------+

数据查询:

-- 根据输入特征向量,检索最相似的前 10 个商品订单
SELECT /*+ _l_force_vector_index_(k=10, lvector.min_score=0) */
    user_id,
    order_id
FROM orders
WHERE region='Beijing'
ORDER BY l2_distance(item_embedding, '[0.077, 0.941, 0.917, 0.347, 0.331, 0.309, 0.127, 0.990]')
LIMIT 10;

-- 根据输入特征向量,检索最相似的前 10 个商品订单,并返回相似分数
SELECT /*+ _l_force_vector_index_(k=10, lvector.min_score=0) */
    user_id,
    order_id,
    _vector_score_(item_embedding, '[0.077, 0.941, 0.917, 0.347, 0.331, 0.309, 0.127, 0.990]')
FROM orders
WHERE region='Beijing'
ORDER BY l2_distance(item_embedding, '[0.077, 0.941, 0.917, 0.347, 0.331, 0.309, 0.127, 0.990]')
LIMIT 10;

参数说明

在索引构建完成后,OLAP 资源组默认开启索引自动优化,查询时会自动选择合适的索引加速查询,如果您需要强制使用或不使用索引,可以在查询时添加 Hint。

索引名称

Hint

说明

二级索引

/*+ _l_force_secondary_index_*/

强制使用二级索引加速查询

/*+ _l_disable_secondary_index_*/

禁用二级索引

搜索索引

/*+ _l_force_search_index_*/

强制使用搜索索引加速查询

/*+ _l_disable_search_index_*/

禁用搜索索引

列存索引

/*+ _l_force_columnar_index_*/

强制使用列存索引加速查询

/*+ _l_disable_columnar_index_*/

禁用列存索引

基础特性

/*+ _l_force_vector_index_*/

强制使用向量索引执行相似度召回

/*+ _l_disable_vector_index_*/

禁用向量索引