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 资源组支持以下数据类型:
类型 | 说明 |
| 布尔值 |
| 8 位整数 |
| 16 位整数 |
| 32 位整数 |
| 64 位整数 |
| 单精度浮点 |
| 双精度浮点 |
| 变长字符串 |
| 二进制数据 |
示例:
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>'
);语法解释:
参数 | 说明 |
| 索引名称 |
| 目标宽表名称 |
| 指定索引数据的分区策略,由普通分区表达式和 bucket 分区表达式共同构成,两类表达式中的字段均须为宽表主键字段 |
普通分区表达式 | 可选,0个或多个宽表主键字段(如日期、城市等低基数字段),用逗号分隔。索引数据按不同分区值分别构建,查询时可按分区条件高效定位。不建议使用高基数字段(如用户ID)作为普通分区键,否则会产生大量小分区 |
| 必填,至少一个。 |
| 列存索引数据写入的目标 Database |
| 列存索引数据写入的目标 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> [, ...])];语法解释:
参数 | 说明 |
| 索引名称 |
| 目标宽表名称 |
| 索引列及排序方向,可指定多列,查询时条件需匹配索引列前缀 |
| 覆盖列,将额外列存入索引,查询时无需回表即可返回这些列的值 |
示例:
-- 为 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> [, ...]);语法解释:
参数 | 说明 |
| 索引名称 |
| 目标宽表名称 |
| 列的索引配置,格式为 |
| 字段类型: |
| 分词器,仅 |
| 是否对该列建立全文索引,设为 |
示例:
-- 为 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 表达式支持以下匹配规则:
语法 | 含义 |
| 包含该词 |
| 必须包含该词 |
| 不能包含该词 |
| 包含完整短语(不分词) |
| 必须包含括号内任一词 |
-- 建表(含文本字段和 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}
语法说明:
变量含义:
变量名
变量含义
${SELECT_LIST}
查询目标列。
_vector_score_(${EMBEDDING_COLUMN}, ${TARGET_VECTOR})
返回相似分数,其中EMBEDDING_COLUMN,和TARGET_VECTOR两个参数需要和DISTANCE_FUNCTION的参数相同。
${TABLE_NAME}
目标表。
${CONDITION}
标量过滤条件。
${DISTANCE_FUNCTION}
相似距离函数,目前支持
l2_distance,cosine_similarity,innerproduct_distance。${EMBEDDING_COLUMN}
构建向量索引列。
${TARGET_VECTOR}
目标向量 (字符串表达的浮点数组)。
${PROPERTIES}
向量检索的支持的参数,比如
k=10,lvector.min_score=0。距离函数:支持
l2_distance,cosine_similarity,innerproduct_distance。Hint:通过
/*+ _l_force_vector_index_(...) */查询向量索引和配置向量查询参数,支持的参数如下:参数
是否必填
说明
k
是
返回最相似的K个数据,请注意参数
k和LIMIT需要保持一致。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 | 说明 |
| 强制使用二级索引加速查询 | |
| 禁用二级索引 | |
| 强制使用搜索索引加速查询 | |
| 禁用搜索索引 | |
| 强制使用列存索引加速查询 | |
| 禁用列存索引 | |
| 强制使用向量索引执行相似度召回 | |
| 禁用向量索引 |