Lakehouse 全文检索使用指南


写在前面

您可能遇到的文本检索场景

场景1:企业知识库搜索系统

当前在Hive/Spark中的常见做法

-- 在Hive中进行文本搜索
SELECT * FROM knowledge_base 
WHERE content LIKE '%人工智能%' 
   OR content LIKE '%机器学习%' 
   OR content LIKE '%深度学习%';

-- 性能问题:
-- 1. 全表扫描,无法利用索引
-- 2. 只能精确匹配,无法进行语义搜索
-- 3. 中文分词困难,搜索效果差

面临的技术挑战

  • 性能限制:LIKE查询需要全表扫描,大数据量时性能极差
  • 功能局限:无法进行分词搜索,只能精确字符串匹配
  • 维护复杂:需要手动管理搜索关键词和同义词
  • 扩展困难:多语言支持需要额外开发

场景2:日志分析与故障排查

在Elasticsearch中的典型实现

// Elasticsearch查询
{
  "query": {
    "multi_match": {
      "query": "ERROR timeout connection",
      "fields": ["message", "stack_trace"]
    }
  }
}

常见的技术痛点

  • 架构复杂:需要维护独立的搜索引擎系统
  • 数据同步:数据需要从数据湖同步到搜索引擎
  • 成本问题:额外的存储和计算资源消耗
  • 一致性风险:数据同步延迟导致搜索结果不准确

为什么需要原生全文检索

基于以上场景中的技术挑战,Lakehouse原生全文检索的设计目标是:

统一的数据处理平台

  • 在同一系统中完成分析计算和全文检索
  • 无需维护独立的搜索引擎系统
  • 数据存储和检索的强一致性

高性能的倒排索引

  • 基于倒排索引的快速文本检索
  • 支持多种分词策略和语言
  • 比传统LIKE查询性能提升数十倍

智能的分词和匹配

  • 支持中文、英文、Unicode等多种分词器
  • 提供短语匹配、前缀匹配、正则匹配等多种模式
  • 自动大小写转换和标点符号过滤

如何使用这份指南

读者角色建议阅读重点预期收获
数据工程师索引创建 → 函数使用 → 性能优化掌握倒排索引的正确使用方法
系统架构师应用场景 → 架构对比 → 迁移策略获得从传统搜索引擎的迁移指导
应用开发者快速开始 → 查询模式 → 避坑指南了解全文检索的最佳实践

快速开始

基本使用流程

-- 1. 创建包含倒排索引的表
CREATE TABLE documents (
    id BIGINT,
    title STRING,
    content STRING,
    created_at TIMESTAMP,
    
    -- 建表时定义倒排索引
    INDEX title_idx (title) INVERTED PROPERTIES('analyzer'='keyword'),
    INDEX content_idx (content) INVERTED PROPERTIES('analyzer'='chinese', 'mode'='smart')
);

-- 2. 插入数据
INSERT INTO documents VALUES 
(1, 'ClickZetta技术指南', '云器Lakehouse支持向量检索和全文搜索功能', CURRENT_TIMESTAMP());

-- 3. 为已有数据构建索引
BUILD INDEX content_idx ON documents;

-- 4. 执行全文检索查询
SELECT id, title FROM documents 
WHERE MATCH_ANY(content, '全文搜索 向量检索', map('analyzer', 'auto'));

-- 5. 使用短语匹配
SELECT id, title FROM documents 
WHERE MATCH_PHRASE(content, '全文搜索功能', map('analyzer', 'auto'));

技术对比:传统方案 vs 原生全文检索

传统LIKE查询方案

-- 使用LIKE进行文本搜索
SELECT * FROM documents 
WHERE content LIKE '%人工智能%' 
   OR content LIKE '%机器学习%'
   OR content LIKE '%深度学习%';

-- 存在的问题:
-- 1. 全表扫描,性能差
-- 2. 无法分词,只能精确匹配
-- 3. 大小写敏感
-- 4. 无法处理同义词

外部搜索引擎方案

# 需要维护额外的Elasticsearch集群
version: '3'
services:
  elasticsearch:
    image: elasticsearch:7.14.0
    environment:
      - discovery.type=single-node
    ports:
      - "9200:9200"
# 需要数据同步脚本
from elasticsearch import Elasticsearch

def sync_data_to_es():
    # 从数据湖读取数据
    # 转换格式
    # 同步到Elasticsearch
    pass

Lakehouse原生全文检索

-- 一站式解决方案
CREATE TABLE documents (
    id BIGINT,
    content STRING,
    INDEX content_idx (content) INVERTED PROPERTIES('analyzer'='chinese')
);

-- 直接使用内置函数
SELECT * FROM documents 
WHERE MATCH_ALL(content, '人工智能 机器学习', map('analyzer', 'auto'));

方案对比总结

特性LIKE查询外部搜索引擎Lakehouse全文检索优势
性能极差(全表扫描)优秀优秀(倒排索引)无需外部系统即可获得高性能
架构复杂度简单复杂简单统一平台,减少运维成本
数据一致性强一致最终一致强一致避免数据同步延迟
开发成本中等减少集成开发工作
分词支持丰富丰富原生支持多语言分词
维护成本无需维护独立搜索集群

倒排索引核心概念

倒排索引原理

基本概念

  • 词典(Dictionary):存储所有文档中出现的唯一单词列表
  • 倒排表(Posting List):记录每个单词在哪些文档中出现及位置信息

构建过程

  1. 分词(Tokenization):将文档内容分割成单词或短语
  2. 标准化(Normalization):转小写、去除停用词等处理
  3. 构建词典:为每个单词分配唯一ID
  4. 构建倒排表:记录单词与文档的映射关系

索引创建语法

建表时定义索引

CREATE TABLE table_name (
    column_definitions,
    INDEX index_name (column_name) INVERTED 
    [COMMENT 'description'] 
    PROPERTIES(
        'analyzer'='english|chinese|keyword|unicode',
        'mode'='smart|max_word'  -- 仅中文分词支持
    )
);

已有表添加索引

CREATE INVERTED INDEX [IF NOT EXISTS] index_name 
ON TABLE [schema.]table_name(column_name)
[COMMENT 'description'] 
PROPERTIES(
    'analyzer'='english|chinese|keyword|unicode',
    'mode'='smart|max_word'
);

支持的数据类型

数据类型类别具体类型是否需要PROPERTIES说明
数值类型TINYINT, SMALLINT, INT, BIGINT, FLOAT, DOUBLE用于等值和范围查询加速
日期类型DATE, TIMESTAMP用于时间范围查询加速
字符串类型STRING, VARCHAR, CHAR必须指定分词器

分词器详解

分词器类型对比

keyword分词器

SELECT TOKENIZE('ClickZetta Lakehouse 技术指南', map('analyzer', 'keyword'));
-- 结果:["ClickZetta Lakehouse 技术指南"]
  • 特点:不分词,保留完整字符串
  • 适用场景:精确匹配、ID字段、状态字段
  • 性能:最优,直接字符串匹配

english分词器

SELECT TOKENIZE('ClickZetta Lakehouse Technical Guide', map('analyzer', 'english'));
-- 结果:["clickzetta", "lakehouse", "technical", "guide"]
  • 特点:识别ASCII字母数字,转小写,过滤标点
  • 适用场景:纯英文内容
  • 性能:优秀,针对英文优化

chinese分词器

SELECT TOKENIZE('ClickZetta Lakehouse 技术指南', map('analyzer', 'chinese'));
-- 结果:["clickzetta", "lakehouse", "技术", "指南"]
  • 特点:支持中英文混合,智能分词
  • 适用场景:中文文档、中英文混合内容
  • 分词模式
    • smart:智能分词,粗粒度,高准确率
    • max_word:最大分词,细粒度,高召回率

unicode分词器

SELECT TOKENIZE('ClickZetta Lakehouse 技術指南', map('analyzer', 'unicode'));
-- 结果:["clickzetta", "lakehouse", "技", "術", "指", "南"]
  • 特点:支持所有Unicode字符
  • 适用场景:多语言混合内容
  • 性能:相对较慢,但支持范围最广

分词模式详解

仅中文分词器支持分词模式:

-- smart模式:智能分词
SELECT TOKENIZE('自然语言处理技术', map('analyzer', 'chinese', 'mode', 'smart'));
-- 结果:["自然语言", "处理", "技术"]

-- max_word模式:最大分词
SELECT TOKENIZE('自然语言处理技术', map('analyzer', 'chinese', 'mode', 'max_word'));
-- 结果:["自然", "语言", "自然语言", "处理", "技术"]

选择建议

  • 短文本匹配:使用smart模式,提高准确率
  • 全文搜索:使用max_word模式,提高召回率

全文检索函数

函数概览

函数名功能返回类型适用场景
TOKENIZE分词测试ARRAY验证分词效果
MATCH_ALL匹配所有关键词BOOLEAN精确搜索
MATCH_ANY匹配任意关键词BOOLEAN宽泛搜索
MATCH_PHRASE短语匹配BOOLEAN顺序敏感搜索
MATCH_PHRASE_PREFIX短语前缀匹配BOOLEAN自动补全
MATCH_REGEXP正则表达式匹配BOOLEAN模式匹配

TOKENIZE - 分词测试函数

TOKENIZE(input, option)

功能:将文本按指定分词器进行分词,用于验证分词效果

参数

  • input:要分词的文本
  • option:分词选项,如map('analyzer', 'chinese')

使用示例

-- 测试不同分词器效果
SELECT 
    'keyword' as analyzer,
    TOKENIZE('机器学习算法', map('analyzer', 'keyword')) as tokens
UNION ALL
SELECT 
    'chinese',
    TOKENIZE('机器学习算法', map('analyzer', 'chinese'))
UNION ALL
SELECT 
    'unicode',
    TOKENIZE('机器学习算法', map('analyzer', 'unicode'));

MATCH_ALL - 全匹配函数

MATCH_ALL(column, query, option)

功能:要求文档包含查询文本中的所有分词结果

逻辑:AND关系,所有词都必须存在

使用示例

-- 查找同时包含"机器学习"和"算法"的文档
SELECT id, title FROM documents 
WHERE MATCH_ALL(content, '机器学习 算法', map('analyzer', 'auto'));

MATCH_ANY - 任意匹配函数

MATCH_ANY(column, query, option)

功能:文档包含查询文本中任意一个分词即可

逻辑:OR关系,任一词存在即可

使用示例

-- 查找包含"人工智能"或"机器学习"或"深度学习"的文档
SELECT id, title FROM documents 
WHERE MATCH_ANY(content, '人工智能 机器学习 深度学习', map('analyzer', 'auto'));

MATCH_PHRASE - 短语匹配函数

MATCH_PHRASE(column, query, option)

功能:要求文档中包含查询短语,且词序必须一致且连续

特点

  • 对词序敏感
  • 要求连续出现
  • 忽略大小写

使用示例

-- 查找包含"自然语言处理"短语的文档
SELECT id, title FROM documents 
WHERE MATCH_PHRASE(content, '自然语言处理', map('analyzer', 'auto'));

-- 反例:不会匹配"自然 语言 处理"(不连续)
-- 反例:不会匹配"语言 自然 处理"(顺序不对)

MATCH_PHRASE_PREFIX - 短语前缀匹配

MATCH_PHRASE_PREFIX(column, query, option)

功能:前n-1个词按短语匹配,最后一个词按前缀匹配

适用场景:搜索建议、自动补全

使用示例

-- 查找以"数据 分"开头的短语(如"数据分析"、"数据分类")
SELECT id, title FROM documents 
WHERE MATCH_PHRASE_PREFIX(content, '数据 分', map('analyzer', 'auto'));

MATCH_REGEXP - 正则匹配函数

MATCH_REGEXP(column, query, option)

功能:对分词结果进行正则表达式匹配

使用示例

-- 查找包含以"学"结尾的词的文档
SELECT id, title FROM documents 
WHERE MATCH_REGEXP(content, '.*学', map('analyzer', 'auto'));

-- 查找包含数字的文档
SELECT id, title FROM documents 
WHERE MATCH_REGEXP(content, '.*[0-9].*', map('analyzer', 'auto'));

重要参数说明

analyzer选项

推荐使用auto参数

map('analyzer', 'auto')  -- 自动匹配列的分词设置

手动指定分词器

map('analyzer', 'chinese')
map('analyzer', 'chinese', 'mode', 'smart')

⚠️ 重要提醒:函数中的分词器必须与索引创建时使用的分词器一致,否则无法利用索引加速!


索引管理

索引生命周期

1. 创建索引

-- 方式1:建表时创建
CREATE TABLE documents (
    id BIGINT,
    content STRING,
    INDEX content_idx (content) INVERTED PROPERTIES('analyzer'='chinese')
);

-- 方式2:为已有表创建
CREATE INVERTED INDEX content_idx ON TABLE documents(content) 
PROPERTIES('analyzer'='chinese', 'mode'='smart');

2. 构建索引(重要!)

-- 对已有数据构建索引(同步任务)
BUILD INDEX content_idx ON documents;

-- 按分区构建索引
BUILD INDEX content_idx ON documents 
WHERE partition_date >= '2024-01-01';

⚠️ 关键提醒

  • CREATE INDEX仅对新增数据生效
  • 已有数据必须执行BUILD INDEX才能利用索引
  • 构建索引会消耗计算资源,建议在业务低峰期执行

3. 查看索引

-- 列出表上所有索引
SHOW INDEX FROM table_name;

-- 查看索引详情(如果环境支持)
DESC INDEX index_name;
DESC INDEX EXTENDED index_name;  -- 包含大小信息

4. 删除索引

DROP INDEX index_name ON table_name;

删除特点

  • 立即删除元数据
  • 索引文件异步清理
  • 不影响数据本身

索引性能调优

分区表索引策略

-- 大表分区构建建议
BUILD INDEX content_idx ON large_table 
WHERE year = '2024' AND month = '01';

BUILD INDEX content_idx ON large_table 
WHERE year = '2024' AND month = '02';
-- 逐个分区构建,避免资源消耗过大

存储成本优化

-- 查看索引存储占用(如果支持)
DESC INDEX EXTENDED index_name;

-- 根据业务需求选择合适的分词器
-- keyword: 存储最少,仅精确匹配
-- chinese: 中等存储,支持智能分词
-- unicode: 存储最多,支持全语言

应用场景设计

企业知识库系统

-- 知识库表设计
CREATE TABLE knowledge_base (
    doc_id BIGINT PRIMARY KEY,
    title STRING,
    content STRING,
    category STRING,
    tags STRING,
    created_at TIMESTAMP,
    updated_at TIMESTAMP,
    
    -- 多层次索引设计
    INDEX title_keyword_idx (title) INVERTED PROPERTIES('analyzer'='keyword'),
    INDEX content_chinese_idx (content) INVERTED PROPERTIES('analyzer'='chinese', 'mode'='smart'),
    INDEX tags_unicode_idx (tags) INVERTED PROPERTIES('analyzer'='unicode')
);

-- 多维度搜索查询
SELECT doc_id, title FROM knowledge_base 
WHERE MATCH_ANY(content, '人工智能 机器学习', map('analyzer', 'auto'))
   OR MATCH_ANY(tags, 'AI ML', map('analyzer', 'auto'))
ORDER BY updated_at DESC LIMIT 20;

日志分析系统

-- 应用日志表
CREATE TABLE application_logs (
    log_id BIGINT,
    timestamp TIMESTAMP,
    level STRING,
    message STRING,
    stack_trace STRING,
    source_ip STRING,
    
    INDEX message_idx (message) INVERTED PROPERTIES('analyzer'='english'),
    INDEX stack_trace_idx (stack_trace) INVERTED PROPERTIES('analyzer'='keyword')
) PARTITIONED BY (DATE(timestamp));

-- 故障排查查询
SELECT log_id, timestamp, message FROM application_logs 
WHERE DATE(timestamp) >= CURRENT_DATE() - INTERVAL '7' DAY
  AND level = 'ERROR'
  AND MATCH_ANY(message, 'timeout connection database', map('analyzer', 'auto'))
ORDER BY timestamp DESC;

电商商品搜索

-- 商品信息表
CREATE TABLE products (
    product_id BIGINT,
    name STRING,
    description STRING,
    brand STRING,
    category STRING,
    tags STRING,
    price DECIMAL(10,2),
    
    INDEX name_chinese_idx (name) INVERTED PROPERTIES('analyzer'='chinese', 'mode'='max_word'),
    INDEX desc_chinese_idx (description) INVERTED PROPERTIES('analyzer'='chinese', 'mode'='max_word'),
    INDEX brand_keyword_idx (brand) INVERTED PROPERTIES('analyzer'='keyword')
);

-- 商品搜索查询
SELECT product_id, name, price FROM products 
WHERE MATCH_ANY(name, '手机 智能 拍照', map('analyzer', 'auto'))
   OR MATCH_ANY(description, '手机 智能 拍照', map('analyzer', 'auto'))
ORDER BY price;

内容管理系统

-- 文章内容表
CREATE TABLE articles (
    article_id BIGINT,
    title STRING,
    content STRING,
    author STRING,
    publish_date DATE,
    status STRING,
    
    INDEX title_chinese_idx (title) INVERTED PROPERTIES('analyzer'='chinese'),
    INDEX content_chinese_idx (content) INVERTED PROPERTIES('analyzer'='chinese', 'mode'='smart'),
    INDEX author_keyword_idx (author) INVERTED PROPERTIES('analyzer'='keyword')
);

-- 内容搜索
SELECT article_id, title, author FROM articles 
WHERE status = 'published'
  AND publish_date >= CURRENT_DATE() - INTERVAL '30' DAY
  AND MATCH_PHRASE(content, '技术发展趋势', map('analyzer', 'auto'))
ORDER BY publish_date DESC;

重要避坑指南

分词器一致性问题

常见错误:分词器不匹配

-- ❌ 错误示例:索引使用chinese分词,查询使用english分词
CREATE TABLE docs (
    content STRING,
    INDEX content_idx (content) INVERTED PROPERTIES('analyzer'='chinese')
);

SELECT * FROM docs 
WHERE MATCH_ANY(content, '测试', map('analyzer', 'english'));
-- 结果:无法利用索引,性能差

正确做法:

-- ✅ 方案1:使用auto参数(推荐)
SELECT * FROM docs 
WHERE MATCH_ANY(content, '测试', map('analyzer', 'auto'));

-- ✅ 方案2:手动匹配索引分词器
SELECT * FROM docs 
WHERE MATCH_ANY(content, '测试', map('analyzer', 'chinese'));

索引构建避坑

BUILD INDEX的必要性

-- ❌ 常见错误:忘记构建索引
CREATE INVERTED INDEX content_idx ON TABLE existing_table(content) 
PROPERTIES('analyzer'='chinese');

-- 直接查询(只对新数据有效,已有数据无法利用索引)
SELECT * FROM existing_table 
WHERE MATCH_ANY(content, '关键词', map('analyzer', 'auto'));

正确的索引构建流程

-- ✅ 完整流程
-- 1. 创建索引
CREATE INVERTED INDEX content_idx ON TABLE existing_table(content) 
PROPERTIES('analyzer'='chinese');

-- 2. 构建索引(必须!)
BUILD INDEX content_idx ON existing_table;

-- 3. 验证索引
SHOW INDEX FROM existing_table;

-- 4. 执行查询
SELECT * FROM existing_table 
WHERE MATCH_ANY(content, '关键词', map('analyzer', 'auto'));

查询性能避坑

亚秒查询的性能限制

根据官方文档:在大多数情况下,倒排索引并不会显著提高执行时间为亚秒的查询的性能

-- ❌ 不适合倒排索引的场景
-- 1. 小数据量表(几百行)
-- 2. 已经很快的查询(<1秒)
-- 3. 简单的等值查询

-- ✅ 适合倒排索引的场景
-- 1. 大数据量表(万行以上)
-- 2. 复杂的文本搜索
-- 3. 多关键词匹配

不支持的查询模式

-- ❌ 不支持:对列进行类型转换
SELECT * FROM docs 
WHERE MATCH_ANY(CAST(id AS STRING), '123', map('analyzer', 'auto'));

-- ✅ 支持:对查询值进行转换
SELECT * FROM docs 
WHERE MATCH_ANY(content, CAST(123 AS STRING), map('analyzer', 'auto'));

-- ❌ 不支持:外部表
-- 倒排索引不支持外部表

存储成本避坑

索引存储开销

-- 倒排索引会创建额外的索引文件
-- 存储成本 = 原始数据 + 索引文件

-- 优化建议:
-- 1. 仅为真正需要搜索的列创建索引
-- 2. 根据查询模式选择合适的分词器
-- 3. 定期清理不必要的索引

分词器选择策略

分词器索引大小查询性能功能丰富度推荐场景
keyword最小最快精确匹配ID、状态、标签
english英文分词纯英文内容
chinese中等中等中文分词中文文档
unicode最大相对慢全语言支持多语言混合

性能优化

查询优化策略

1. 合理选择查询函数

-- 根据业务需求选择合适的函数
-- 精确搜索:使用 MATCH_ALL
SELECT * FROM docs WHERE MATCH_ALL(content, '机器学习 算法', map('analyzer', 'auto'));

-- 宽泛搜索:使用 MATCH_ANY  
SELECT * FROM docs WHERE MATCH_ANY(content, '人工智能 机器学习 深度学习', map('analyzer', 'auto'));

-- 短语搜索:使用 MATCH_PHRASE
SELECT * FROM docs WHERE MATCH_PHRASE(content, '自然语言处理', map('analyzer', 'auto'));

2. 组合查询优化

-- ✅ 推荐:将全文检索作为主要过滤条件
SELECT * FROM documents 
WHERE MATCH_ANY(content, '关键词', map('analyzer', 'auto'))
  AND category = 'tech'  -- 在全文检索基础上进行二次过滤
  AND created_at >= '2024-01-01';

-- ⚠️ 注意:避免在大量数据上先进行非索引过滤
SELECT * FROM documents 
WHERE category = 'tech'  -- 如果category没有索引,会先全表扫描
  AND MATCH_ANY(content, '关键词', map('analyzer', 'auto'));

3. 分页查询优化

-- ✅ 高效的分页查询
SELECT id, title FROM documents 
WHERE MATCH_ANY(content, '关键词', map('analyzer', 'auto'))
ORDER BY id  -- 使用主键排序
LIMIT 20 OFFSET 0;

-- ⚠️ 避免深度分页
-- LIMIT 20 OFFSET 10000; -- 性能会随offset增大而下降

索引优化策略

1. 分区表索引管理

-- 按分区逐步构建索引
BUILD INDEX content_idx ON large_table 
WHERE year = '2024' AND month = '06';

-- 监控构建进度
-- 可通过Job Profile查看进度

2. 索引维护策略

-- 定期检查索引状态
SHOW INDEX FROM table_name;

-- 对于经常更新的表,可能需要重建索引
DROP INDEX old_idx ON table_name;
CREATE INVERTED INDEX new_idx ON TABLE table_name(column) 
PROPERTIES('analyzer'='chinese');
BUILD INDEX new_idx ON table_name;

系统资源优化

1. 计算资源配置

  • 索引构建:使用较大的Virtual Cluster进行BUILD INDEX操作
  • 查询执行:可使用较小的Virtual Cluster进行日常查询
  • 混合负载:分离索引构建和查询工作负载

2. 存储资源优化

-- 监控索引存储占用(如果支持)
DESC INDEX EXTENDED index_name;

-- 清理不必要的索引
DROP INDEX unused_idx ON table_name;

迁移策略

从传统LIKE查询迁移

迁移评估

适合迁移的场景

  • 频繁的文本搜索查询
  • 大数据量表(万行以上)
  • 复杂的多关键词搜索
  • 需要中文分词的场景

不急于迁移的场景

  • 小数据量表
  • 偶尔的文本查询
  • 已经很快的简单查询(<1秒)

迁移步骤

-- 1. 分析现有查询模式
-- 识别频繁的LIKE查询
SELECT query_text, execution_count 
FROM query_logs 
WHERE query_text LIKE '%LIKE%'
ORDER BY execution_count DESC;

-- 2. 创建测试表验证效果
CREATE TABLE docs_test AS SELECT * FROM docs_original LIMIT 1000;

-- 3. 添加倒排索引
CREATE INVERTED INDEX content_idx ON TABLE docs_test(content) 
PROPERTIES('analyzer'='chinese');

BUILD INDEX content_idx ON docs_test;

-- 4. 性能对比测试
-- 原始LIKE查询
SELECT COUNT(*) FROM docs_test WHERE content LIKE '%关键词%';

-- 全文检索查询
SELECT COUNT(*) FROM docs_test 
WHERE MATCH_ANY(content, '关键词', map('analyzer', 'auto'));

-- 5. 逐步迁移生产环境

从外部搜索引擎迁移

Elasticsearch迁移对照

Elasticsearch查询Lakehouse全文检索说明
match_allMATCH_ALL匹配所有关键词
matchMATCH_ANY匹配任意关键词
match_phraseMATCH_PHRASE短语匹配
match_phrase_prefixMATCH_PHRASE_PREFIX短语前缀匹配
regexpMATCH_REGEXP正则表达式匹配

迁移收益评估

架构简化收益

  • 减少1个独立的搜索引擎系统
  • 统一数据存储和检索平台
  • 降低运维复杂度

成本优化收益

  • 减少额外的存储和计算资源
  • 无需数据同步ETL流程
  • 降低系统总体拥有成本

数据一致性收益

  • 强一致性保证
  • 无数据同步延迟
  • 实时搜索最新数据

混合方案设计

对于复杂的企业环境,可以采用混合方案:

-- 方案1:按数据类型分离
-- 结构化查询 + 简单文本搜索:使用Lakehouse全文检索
-- 复杂语义搜索 + 推荐算法:保留Elasticsearch

-- 方案2:按实时性分离  
-- 实时搜索:使用Lakehouse全文检索
-- 离线分析:使用Elasticsearch

-- 方案3:按数据规模分离
-- 大数据量:使用Lakehouse全文检索
-- 小数据量快速原型:使用Elasticsearch

最佳实践总结

索引设计最佳实践

1. 分词器选择原则

-- 根据数据特点选择分词器
CREATE TABLE multilingual_docs (
    id BIGINT,
    title_cn STRING,      -- 中文标题
    title_en STRING,      -- 英文标题  
    content STRING,       -- 混合内容
    tags STRING,          -- 标签(精确匹配)
    
    INDEX title_cn_idx (title_cn) INVERTED PROPERTIES('analyzer'='chinese', 'mode'='smart'),
    INDEX title_en_idx (title_en) INVERTED PROPERTIES('analyzer'='english'),
    INDEX content_idx (content) INVERTED PROPERTIES('analyzer'='unicode'),
    INDEX tags_idx (tags) INVERTED PROPERTIES('analyzer'='keyword')
);

2. 索引维护策略

-- 生产环境索引维护流程
-- 1. 非峰期创建索引
CREATE INVERTED INDEX content_idx ON TABLE large_table(content) 
PROPERTIES('analyzer'='chinese');

-- 2. 分批构建索引
BUILD INDEX content_idx ON large_table 
WHERE partition_date = '2024-06-01';

-- 3. 验证索引效果
SELECT COUNT(*) FROM large_table 
WHERE MATCH_ANY(content, '测试关键词', map('analyzer', 'auto'));

-- 4. 监控索引状态
SHOW INDEX FROM large_table;

查询模式最佳实践

1. 查询函数选择指南

业务场景推荐函数示例查询
精确搜索多个关键词MATCH_ALL必须包含"AI"和"机器学习"
宽泛主题搜索MATCH_ANY包含"AI"或"ML"或"深度学习"
专业术语搜索MATCH_PHRASE精确匹配"自然语言处理"
搜索建议/自动补全MATCH_PHRASE_PREFIX以"数据分"开头的短语
模式匹配MATCH_REGEXP包含数字或特定格式

2. 性能优化查询模式

--  高效查询模式
-- 1. 利用分区过滤
SELECT * FROM logs 
WHERE log_date >= CURRENT_DATE() - INTERVAL '7' DAY
  AND MATCH_ANY(message, 'ERROR timeout', map('analyzer', 'auto'));

-- 2. 组合索引过滤
SELECT * FROM products 
WHERE category = 'electronics'  -- 假设category有普通索引
  AND MATCH_ANY(name, '手机 智能', map('analyzer', 'auto'));

-- 3. 限制返回结果
SELECT id, title FROM documents 
WHERE MATCH_ANY(content, '关键词', map('analyzer', 'auto'))
ORDER BY id LIMIT 100;  -- 避免返回过多结果

监控和诊断

1. 索引效果验证

-- 验证索引是否被使用(通过执行计划)
EXPLAIN SELECT * FROM documents 
WHERE MATCH_ANY(content, '关键词', map('analyzer', 'auto'));

-- 对比LIKE查询性能
-- 方法:记录查询执行时间,对比优化效果

2. 常见问题诊断

-- 检查分词效果
SELECT TOKENIZE('测试文本', map('analyzer', 'auto'));

-- 检查索引状态
SHOW INDEX FROM table_name;

-- 验证查询语法
SELECT MATCH_ANY('测试文本', '关键词', map('analyzer', 'chinese'));

已知限制与注意事项

功能限制

1. 不支持的场景

  • 外部表:倒排索引不支持外部表
  • 列类型转换:不支持对表列进行强制类型转换

2. 查询限制

-- ❌ 不支持的查询模式
-- 1. 对表列进行类型转换
WHERE MATCH_ANY(CAST(column AS STRING), 'value', map('analyzer', 'auto'))

-- 2. 在外部表上创建倒排索引
CREATE INVERTED INDEX idx ON EXTERNAL_TABLE table_name(column) 
PROPERTIES('analyzer'='chinese');

性能考虑

1. 索引构建成本

  • BUILD INDEX是同步操作,会消耗计算资源
  • 大表建议分区逐步构建
  • 建议在业务低峰期执行

2. 存储成本

  • 倒排索引会创建额外的索引文件
  • 索引大小取决于数据量和分词器类型
  • 需要在查询性能和存储成本间平衡

运维注意事项

1. 版本兼容性

  • 建议在测试环境充分验证
  • 关注版本更新和功能改进

2. 备份恢复

  • 索引元数据会随表结构备份
  • 索引文件需要重新构建
  • 恢复后需要执行BUILD INDEX

快速参考卡片

分词器选择速查

-- 精确匹配(ID、状态等)
'analyzer'='keyword'

-- 纯英文内容
'analyzer'='english'

-- 中文内容(推荐)
'analyzer'='chinese', 'mode'='smart'

-- 多语言混合
'analyzer'='unicode'

-- 自动匹配(推荐)
'analyzer'='auto'

常用查询模板

-- 1. 基础文本搜索
SELECT * FROM table_name 
WHERE MATCH_ANY(column, '关键词', map('analyzer', 'auto'));

-- 2. 精确短语搜索
SELECT * FROM table_name 
WHERE MATCH_PHRASE(column, '精确短语', map('analyzer', 'auto'));

-- 3. 多条件组合搜索
SELECT * FROM table_name 
WHERE MATCH_ALL(content, '关键词1 关键词2', map('analyzer', 'auto'))
  AND category = 'target_category';

-- 4. 分页查询
SELECT id, title FROM table_name 
WHERE MATCH_ANY(content, '关键词', map('analyzer', 'auto'))
ORDER BY id LIMIT 20 OFFSET 0;

索引管理命令

-- 创建索引
CREATE INVERTED INDEX idx_name ON TABLE table_name(column) 
PROPERTIES('analyzer'='chinese');

-- 构建索引
BUILD INDEX idx_name ON table_name;

-- 查看索引
SHOW INDEX FROM table_name;

-- 删除索引
DROP INDEX idx_name ON table_name;

注意:本文档基于Lakehouse 2025年6月的产品文档整理,建议定期查看官方文档获取最新更新。在生产环境中使用前,请务必在测试环境中验证所有操作的正确性和性能影响。

联系我们
预约咨询
微信咨询
电话咨询