尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

StarRocks 的全文检索能力怎么样?内表倒排索引、MATCH 查询与 SQL 分析

StarRocks 的全文检索能力怎么样?内表倒排索引、MATCH 查询与 SQL 分析 中文、英文与多语言分词倒排索引与MATCH谓词结构化过滤、Join 和聚合在一份存算分离内表中完成。作者周康阿里云开源 OLAP 引擎团队负责人数据说明本文示例均为通用化、参数化示例不包含客户或实际业务数据性能部分仅给出评测方法不披露内部实测结果。先给结论如果全文命中结果还要继续执行租户、时间、权限过滤、Join 和聚合StarRocks 的优势是把文本、倒排索引和业务字段保存在同一张内表中。Stella 2.2 可通过 GIN 索引与 MATCH、MATCH_ANY、MATCH_ALL 快速定位 Row IDs并让命中行直接进入 SQL 分析链路。判断 StarRocks 的全文检索能力不能只看是否支持关键词查询还要同时看分词器、查询语义、索引下推、数据新鲜度、结构化过滤、Join、聚合以及 Query Profile 可观测性。用户提出的问题也不再只是确定的等值与范围条件查找包含“连接重置”和“对象存储”的错误日志在支付工单中寻找同时提到“重复扣款”和“退款”的记录从商品标题和详情中找出包含某组关键词的内容在某个租户、时间段和权限范围内检索知识库段落再继续聚合热点问题。如果没有全文索引数据库通常需要逐行读取长文本并执行字符串匹配。即使最终只命中少量记录也可能先扫描海量文本。传统架构通常会在分析数据库之外增加独立搜索系统文本搜索在另一套引擎中完成聚合和业务分析再回到 OLAP。随着数据量和字段增加这条链路会带来新的同步、治理与运维成本同一份数据维护两套存储写入、更新和删除需要同步Schema、分词器和索引版本需要跨系统管理搜索命中的 ID 还要回到分析库做权限过滤、Join 与聚合两套系统的数据可见时间不同问题定位和一致性保障更复杂。那么能否让已经进入分析内表的文本直接可搜EMR Serverless StarRocks Stella 2.2 可以把内表全文/倒排索引与结构化 SQL 谓词、向量检索和 OLAP 分析组合在同一条查询链路中。用户仍然使用 SQL通过MATCH、MATCH_ANY和MATCH_ALL快速定位文本行并继续执行分组、关联和统计。图 1当文本持续更新、命中结果还要参与 WHERE、JOIN 与聚合时StarRocks 内表可以把文本、GIN 倒排索引和业务字段放在一份数据中由一条 SQL 完成检索与分析。01 StarRocks 为什么需要全文索引而不是逐行扫描传统 OLAP 减少扫描量主要依赖三类机制列式存储只读取查询需要的列物理排序与分区让时间、租户等数据在存储上聚集Zone Map记录数据块内的最小值与最大值跳过不可能命中的块。这套机制对时间范围、数值条件和聚集度较高的字段非常有效但文本关键词并不遵循同样的物理规律。假设一张大规模商品评论表按review_date排序。查询本季度评论时目标数据物理上相对连续但查询正文中同时出现battery、life和poor的评论时命中行会离散分布在许多日期和数据块中。Zone Map 只能描述一个数据块的极值范围无法回答“这一块文本里是否出现了某个词”。排序键也只有有限维度把表改为按产品 ID 排序可能有利于产品查询却不会让任意关键词在物理上聚集。没有全文索引时类似查询只能逐行执行字符串匹配SELECTreview_id,product_id,review_bodyFROMamazon_reviewsWHEREreview_bodyLIKE%battery life poor%;这不只是 I/O 问题。每一行还需要执行字符串扫描、大小写处理或模式匹配并发增加后CPU 和内存带宽会被大量最终不命中的文本消耗。全文检索的核心挑战因此变成如何先知道关键词出现在哪些行再只读取这些行02 倒排索引如何把“逐行找词”变成“按词找行”普通列式存储保存的是“行到值”的映射Row 1 → “对象存储连接超时” Row 2 → “计算节点内存不足” Row 3 → “对象存储请求被重置”全文倒排索引保存的则是“词到行”的映射“对象” → [Row 1, Row 3] “存储” → [Row 1, Row 3] “连接” → [Row 1] “重置” → [Row 3]当查询要求同时包含“对象存储”和“连接”时引擎不必扫描三行原文而是读取相关词项的倒排列表并对 Row ID 集合求交集[Row 1, Row 3] ∩ [Row 1] [Row 1]真实数据中倒排列表会采用更紧凑的编码和高效集合运算但基本思想不变先通过词典定位词项再通过 Posting List 定位行号最后读取真正需要的业务列。MATCH单个查询表达式MATCH用于匹配一个查询表达式。它也支持前缀或通配形式但具体效果取决于分词器、索引实现和查询写法。WHEREmessageMATCHconnectionMATCH_ANY多个词任意命中MATCH_ANY对应 OR 语义只要命中任意查询词即可返回WHEREmessage MATCH_ANYtimeout reset refused它适合扩大召回例如检索多种常见连接异常。MATCH_ALL多个词同时命中MATCH_ALL对应 AND 语义要求查询词全部出现WHEREmessage MATCH_ALLobject storage timeout它能显著缩小候选集适合问题定位和更精确的关键词组合。图 2写入时通过 Analyzer、Dictionary 和 Posting List 建立词项到 Row ID 的映射查询时用 AND/OR 集合运算直接得到候选行再继续过滤、Join 与聚合。03 parser 怎么选中文、英文还是多语言倒排索引能否返回符合预期的结果很大程度上取决于分词器。Stella 内表全文索引可按文本语言和查询需求选择不同的parser。parser适用场景关键特点english英文日志、工单、知识库按非字母字符切分英文转小写chinese中文文本使用中文分析器切分词项standard中英混合、多语言文本基于 Unicode 文本分段适合常见混合语言none精确值、子串或普通谓词加速不进行全文分词查询能力与分词索引不同英文大小写english和standard会把英文词项转为小写。因此查询条件也应使用小写关键词才能正确利用索引定位数据。中文词边界中文没有天然空格。一个业务词是被拆成单字、二元组还是词语会影响 Recall 与 Precision。商品简称、车型、错误码等领域词汇应使用代表性查询集验证不能仅凭几条样例选择分词器。不分词索引当parser none时索引不做全文分词可用于LIKE、MATCH及部分普通谓词的过滤加速。它适合 URL、错误码、设备标识、路径等不希望被语言分词器拆开的字段。但“未分词”不等于任意表达式都能命中索引。例如用于索引过滤的关键词通常需要是字符串字面量不满足支持形态的LIKE可能正常执行却退化为普通扫描。04 内表全文检索如何进入 SQL 分析链路索引与数据文件共同组织内表数据仍然按列存放在数据文件中全文索引围绕被索引的文本列建立词典和 Row ID 映射。查询时倒排索引先过滤数据行后续 Scan 再读取最终需要的列。Stella 2.2 面向存算分离内表的多模态检索可以把全文/倒排过滤与向量检索、结构化 SQL 谓词组合到同一查询流程。对应用而言搜索结果不再只是孤立的文档 ID而是可以直接继续参与租户、权限、状态和时间过滤与商品、设备、客户或知识库元数据表 JoinCOUNT、AVG、GROUP BY等分析计算与向量候选做并集、交集或 RRF 融合生成 RAG 上下文、训练样本或运营报表。共享存储使用内置倒排实现在存算分离的 shared-data 集群中需要使用 StarRocks 内置倒排索引实现Stella 会在该架构下选择兼容实现。它基于原生 Bitmap 能力组织索引可同时服务 shared-data 与 shared-nothing 场景。这条边界很重要不同版本、不同存储架构下的倒排实现并不完全相同。生产建表语法、分词器和高级参数应以 Stella 2.2 实例实际支持为准不能把其他版本或其他产品的参数直接复制到生产环境。05 如何创建 GIN 索引并使用 MATCH 查询下面创建一张存放应用日志的内表。message使用中英混合分词request_path不分词以覆盖两种常见检索需求。CREATETABLEapplication_logs(log_idBIGINTNOTNULL,tenant_idBIGINTNOTNULL,event_timeDATETIMENOTNULL,service_nameVARCHAR(128),severityVARCHAR(16),request_pathVARCHAR(1024),message STRING,INDEXidx_message(message)USINGGIN(parserstandard,imp_libbuiltin),INDEXidx_path(request_path)USINGGIN(parsernone,imp_libbuiltin))ENGINEOLAPDUPLICATEKEY(log_id,tenant_id,event_time)PARTITIONBYdate_trunc(day,event_time)DISTRIBUTEDBYHASH(tenant_id)BUCKETS16;全文索引列需要使用CHAR、VARCHAR或STRING类型。建表完成后确认会话开启索引过滤SETenable_gin_filtertrue;检索包含任意异常词的日志SELECTevent_time,service_name,severity,messageFROMapplication_logsWHEREtenant_id:tenant_idANDevent_time:start_timeANDmessage MATCH_ANYtimeout reset refusedORDERBYevent_timeDESCLIMIT100;这里有两层裁剪时间分区先排除无关日期倒排索引再定位包含任意异常词的行。检索同时满足多个关键词的记录SELECTevent_time,service_name,request_path,messageFROMapplication_logsWHEREtenant_id:tenant_idANDseverityIN(ERROR,FATAL)ANDmessage MATCH_ALL对象 存储 超时ORDERBYevent_timeDESCLIMIT100;MATCH_ALL通过 Posting List 交集缩小候选范围结构化谓词继续保证租户和级别等硬条件。对命中日志直接做聚合分析SELECTservice_name,COUNT(*)ASerror_count,MIN(event_time)ASfirst_seen,MAX(event_time)ASlast_seenFROMapplication_logsWHEREevent_timeNOW()-INTERVAL24HOURANDmessage MATCH_ANYtimeout reset refusedGROUPBYservice_nameORDERBYerror_countDESCLIMIT20;这类查询体现了内表全文检索的价值全文召回不是终点命中行可以直接进入 OLAP 聚合不需要把 ID 导回另一个系统。为已有表添加索引CREATEINDEXidx_messageONapplication_logs(message)USINGGIN(parserstandard,imp_libbuiltin);已有大表加索引会触发表结构变更并消耗构建资源。应在业务低峰执行并通过版本对应的 Schema Change 状态命令确认完成后再进行压测。06 通配与子串查询如何避免扫描整个词典日志、URL 和商品编码经常需要子串匹配例如搜索%rock%、%timeout%或某段路径。全文索引虽然避免了扫描原文但在高基数字典上通配查询仍可能遍历大量词项。内置倒排实现提供dict_gram_num可以在索引词典上再建立 n-gram 字典索引。例如设置为2时词项starrocks会被拆成st, ta, ar, rr, ro, oc, ck, ks查询%rock%时同样拆出ro、oc、ck先用这些 n-gram 缩小候选词项再验证完整模式从而避免全量扫描词典。CREATEINDEXidx_path_gramONapplication_logs(request_path)USINGGIN(parsernone,imp_libbuiltin,dict_gram_num2);选择 n-gram 大小时需要权衡值较小能更好支持短查询模式但会生成更多 n-gram增加索引体积值较大索引更紧凑但短于该长度的查询无法利用 n-gram 字典该参数只适用于内置倒排实现使用前应确认 Stella 2.2 实例是否开放对应能力。07 如何确认全文查询真的命中倒排索引全文查询能够返回结果不代表一定走了倒排索引。上线前需要验证两件事。检查查询形态对已分词的索引列MATCH、MATCH_ANY和MATCH_ALL需要出现在WHERE中并直接作用于建有 GIN 索引的列。查询词需要是字符串字面量。以下写法不满足索引下推要求-- MATCH 不在 WHERE 中SELECTmessageMATCHtimeoutFROMapplication_logs;-- MATCH 作用于未建 GIN 索引的列SELECT*FROMapplication_logsWHEREservice_nameMATCHpayment;查看 Query Profile执行实际查询后在 Scan 节点重点查看指标含义GinFilterRows全文倒排索引过滤的行数GinFilter全文倒排过滤耗时评测时还应记录总扫描行数、返回行数、分区裁剪、读取字节数和查询 P95/P99。只有GinFilterRows与扫描量变化相互印证才能确认加速来自索引而不是缓存、分区或结果集变化。如果索引没有生效优先检查enable_gin_filter是否开启查询列是否确实建有 GIN 索引parser与查询语言、大小写是否匹配MATCH是否位于WHERE并直接作用于索引列查询词是否为字面量未分词索引的LIKE是否符合可下推形式shared-data 实例是否使用内置倒排实现。08 如何评测 StarRocks 全文检索性能建议建立两张除索引外完全一致的测试表一张保留逐行文本扫描路径另一张为目标文本列建立 GIN 索引。测试数据应来自公开数据集或脱敏样本并覆盖短文本、长文本、高频词、低频词和不同命中选择率。查询集至少应覆盖单词命中、多词任意命中和多词同时命中全文条件与时间、类别、权限等结构化条件的组合过滤命中结果继续参与排序、聚合和 Join 的分析链路不同分词器、缓存状态与并发条件下的稳定性。测试报告应同时记录版本与环境、数据分布、索引体积和构建时间、吞吐与延迟分位、错误率、扫描行数与字节数以及 Query Profile 中的索引过滤指标。只有索引过滤指标与扫描量变化相互印证才能确认收益来自倒排索引而不是缓存、分区裁剪或结果集变化。对外发布性能结论前应使用目标生产版本完成同口径复测并公开测试方法和适用边界不直接引用其他环境的加速倍数。09 全文索引有哪些存储、写入与召回成本索引会增加存储全文索引需要保存词典和 Posting List。文本越长、不同词越多索引体积越大。对标题、摘要和正文同时建索引成本也会叠加。写入需要分词和建索引数据导入后需要对文本分词并生成倒排结构因此写入 CPU、内存与耗时会增加。大批量历史数据回灌和存量表加索引应在独立窗口进行并观察 Compaction 与在线查询资源竞争。分词器影响 Recall 与 Precision索引更快并不等于结果一定更好。中文领域词被错误拆分英文缩写大小写不一致错误码被标点切开都可能导致漏召回或误召回。高频词未必带来巨大收益如果某个词出现在绝大多数行中即使索引能快速找到 Posting List后续仍需读取大量命中行。倒排索引最擅长的是选择率较高的关键词和组合条件而不是让任何文本查询都固定提速同一个倍数。因此建索引应从真实查询出发高频搜索的文本列优先很少被搜索的长正文不一定值得建立完整索引URL、编码与自然语言也不应该盲目使用同一个分词器。10 内表全文检索和 Paimon 全文检索怎么选Stella 2.2 同时支持内表与 Paimon 湖表的多模态检索但两条路径的索引组织和查询能力并不完全相同。内表全文检索内表围绕 Segment 与数据文件组织 GIN 倒排索引适合更新更频繁、在线时效要求更高并且需要把关键词过滤与结构化 SQL、Join 和聚合紧密结合的场景。本文示例聚焦内表MATCH过滤。它的核心是快速筛选 Row ID并不等同于 Paimon Tantivyscore()Top-N 的 BM25 排名接口。Paimon 湖表全文检索Paimon 通过 Global Index 管理 Tantivy 全文索引支持带score()的全文 Top-N并可与 BTree/Bitmap 前置过滤和 ANN 向量召回组合。它更适合数据量极大、长期沉淀在对象存储、强调开放湖格式和多模态资产管理的场景。简单选型是在线检索与分析一体化优先内表超大规模、开放湖上资产优先 Paimon。应用可以共享 Stella 的 SQL 和分析体系但应根据实际表类型使用对应的索引定义与评分能力。11 StarRocks 全文检索适合哪些场景综合来看StarRocks 的内表全文检索已经覆盖生产选型的关键环节GIN 倒排索引、多语言分词、MATCH 查询、结构化过滤、Join、聚合与 Query Profile 可观测性。倒排索引把“逐行扫描文本”转换为“通过词项直接定位 Row ID”而 StarRocks 的 SQL 执行能力让这些 Row ID 可以立即进入租户与权限过滤、Join、聚合和分析。文本不必为了可搜被复制成第二份事实数据搜索结果也不必在应用层重新拼装。Stella 2.2 的价值是让存算分离内表同时承载结构化字段、文本、向量和业务指标关键词由全文索引定位语义相似由向量索引补充确定性条件由普通 SQL 守住边界最终仍由同一条查询链路输出可分析、可审计的结果。对于正在维护“分析数据库 独立搜索系统 数据同步”链路的团队是否迁移不能只看一次单词搜索的耗时。更值得评估的是在真实查询集下能否用更少的数据副本、更短的链路和统一的可观测体系同时满足检索性能、数据新鲜度和分析复杂度。参考资料阿里云 EMR Serverless StarRocksStella 2.2.0发布多模态处理与分析闭环内表与湖表统一检索EMR Serverless StarRocks 内核版本说明StarRocks Full-text inverted index 文档
返回列表