Uh oh!
There was an error while loading. Please reload this page.
[feature](inverted index) approximate gram index for LIKE/REGEXP push-down via ngram tokenizer mode=sparse|dense on SNII - #67538
Draft
airborne12 wants to merge 6 commits into
Draft
Conversation
…tor, boolean query, regex AST, Cox-style compiler, differential fuzz) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01METuP3aVRn8dfCU62PivnF
…-only SNII write path Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01METuP3aVRn8dfCU62PivnF
…with approximate (superset) index results Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01METuP3aVRn8dfCU62PivnF
…/index constraints Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01METuP3aVRn8dfCU62PivnF
…in and CREATE INDEX default fixes Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01METuP3aVRn8dfCU62PivnF
hello-stephen
commented
Sep 4, 2026
Contributor
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
All comments in the gram index code, tests and regression suite are now in English. No behaviour change: the only non-comment edit is a gtest failure message that is printed after an assertion already failed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01METuP3aVRn8dfCU62PivnF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What problem does this PR solve?
Issue Number: close #xxx
Related PR: #xxx
Problem Summary:
LIKE '%literal%'andREGEXPon text columns always scan every row today. This PR adds an approximate gram index for them, built on the existing inverted-index machinery, so that a regex/LIKE first prunes rows through the index and the original expression is then re-evaluated only on the surviving candidates. Results are always identical to the non-indexed evaluation: the index only ever produces a superset of the matching rows, and every index-side failure degrades to "no acceleration".No new index type, tokenizer type or
parservalue is introduced. The feature is switched on by giving the built-inngramtokenizer amode:How it works (BE):
be/src/storage/index/inverted/gram/):GramScheme(parameters),GramExtractor(ASCII runs are cut into byte grams — dense sliding window or sparse content-defined-boundary grams,densityselects boundary probability — while every non-ASCII code point becomes its own 1-gram, so CJK text works without a language tokenizer),GramQuery(AND/OR/ALL/NONE tree with simplification and a text serialization), a RE2-subset regex parser, andRegexGramCompiler(Cox 2012 style derivation of the grams a match must contain, for both REGEXP and LIKE). A differential fuzz test checks the compiler against RE2 over hundreds of thousands of random pattern/text pairs and asserts it never drops a matching row.NGramTokenizerFactoryreturns aGramTokenizerwhenmodeis set; gram-family analyzers are recognised by the SNII writer, which forces a docs-only index for them (support_phraseis ignored). Analyzers that carry token filters or char filters are deliberately treated as not gram-family, because their terms would no longer correspond to the raw column value.InvertedIndexQueryType::GRAM_BOOLEAN_QUERYevaluates a serializedGramQueryon the SNII index (df-first AND with early exit, OR union).FunctionLike/FunctionRegexpLikeimplementevaluate_inverted_index: constant pattern → compile → gram query → candidate bitmap flagged as approximate. Approximate results go into a separate table inIndexExecContext;SegmentIteratoronly intersects them into_row_bitmapwhen the conjunct root is the function itself, never marks the column as "index evaluated", and keeps the conjunct for re-evaluation.NOT LIKE/NOT REGEXP/ OR-nested predicates are therefore never pruned. Push-down happens only for SNII readers; CLucene-format readers reject the new query type.SniiCoreMetadataPB.gram_schemeis reserved (encoded/decoded, not yet written) for a later per-segment adaptive mode.FE:
NGramTokenizerValidatoraccepts and validatesmode(auto|sparse|dense),density[0.001, 1],stop_gram_df[0, 1],lower_case, and the gram-family ranges ofmin_gram/max_gram(modeabsent keeps the legacy behaviour byte for byte).IndexPolicyMgrrejects gram tokenizers combined with token filters (use the tokenizer's ownlower_case=trueinstead of alowercasefilter, because folding must happen before gram boundaries are computed).InvertedIndexUtilrequiresinverted_index_storage_format = SNIIfor gram-family indexes, rejectssupport_phrase = trueand index-level char filters, and defaultssupport_phrasetofalse(also forCREATE INDEX/ALTER TABLE ADD INDEX).Observability:
RowsGramIndexFilteredandGramIndexCandidateRowsin the scan profile; BE configenable_gram_index_regexp(defaulttrue) is the kill switch.Known limitations of this first step:
mode=autocurrently behaves assparse;stop_gram_dfis validated and persisted but does not prune high-frequency grams yet;(?i)patterns and LIKE with a customESCAPEare evaluated without the index; the speed-up depends on pattern selectivity and on how much of the column would otherwise be read (the index cuts scanned bytes by orders of magnitude on selective patterns; on a fully page-cached single node the wall-clock gain is smaller).Release note
Regex / LIKE predicates on text columns can be accelerated by an inverted index built with the
ngramtokenizer inmode=sparse|dense(SNII storage format). Query results are unchanged; unsupported patterns fall back to the normal evaluation.Check List (For Author)
Test
inverted_index_p0/gram/test_gram_regexp_like: 139 REGEXP/RLIKE/LIKE/NOT/compound queries compared with the index enabled and disabled, before and after DELETE, across two rowsets and three coexisting indexes on one column; profile asserts the gram index pruned rows)Behavior changed:
ngramtokenizer properties (mode,density,stop_gram_df,lower_case); newGRAM_BOOLEAN_QUERYinverted index query type;LIKE/REGEXPmay use a gram-family SNII index (results unchanged); new BE configenable_gram_index_regexp; new profile countersRowsGramIndexFiltered/GramIndexCandidateRows. Existingngramtokenizers withoutmodeare unaffected.Does this need documentation?
Check List (For Reviewer who merge this PR)
🤖 Generated with Claude Code
https://claude.ai/code/session_01METuP3aVRn8dfCU62PivnF