Skip to content

Support prefix-only search#46

Merged
klauspost merged 2 commits into
minio:mainfrom
klauspost:prefix-only-search
Jun 30, 2026
Merged

Support prefix-only search#46
klauspost merged 2 commits into
minio:mainfrom
klauspost:prefix-only-search

Conversation

@klauspost

@klauspost klauspost commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

When searching for the prefix only, an empty table can be used to reject blocks.

Before/after:

λ mz sidecar build -search.prefix=co64 DJI_20260429201005_0016_D.MP4.mz

λ mz search -v -c co64 DJI_20260429201005_0016_D.MP4.mz
DJI_20260429201005_0016_D.MP4.mz: using sidecar DJI_20260429201005_0016_D.MP4.mz.mzs
DJI_20260429201005_0016_D.MP4.mz: search info: matchLen=6 baseTableSize=23 (8388608 entries) long-prefix="co64"
6
DJI_20260429201005_0016_D.MP4.mz took 6.522s 2332.0 MB/s
Blocks total: 1814, skipped: 0 (0.0%), deferred: 0 (0.0%, 0 skipped)
Blocks searched: 1814 (100.0%), false positive: 1810 (99.8%)
Bytes skipped: 0 compressed, searched: 15208999211 uncompressed
Tables: 1814 present, 0 missing, 1814 unusable
Table bits/byte: 0.0000, log2: 8.0, avg reductions: 15.0
Table total: 39912 bytes, avg 22 bytes/table, 0.00% of 15208999211 uncompressed
Table population: avg 0.0%, min 0.0%, max 0.0%
Table types: 0 uncompressed (0x45), 1814 compressed (0x46)
Compressed tables: 1814 (100.0% of total), 39912 wire bytes, 58048 uncompressed bitmap bytes (68.76% ratio)
 Sub-blocks: 0 total (0 tabled, 0 raw, 0 RLE, 0 sparse); 0 tables emitted (share=0.00 tables/tabled-block)
 Payload bytes: tabled=0 raw=0 RLE=0 sparse=0; table-header bytes=0

λ go build&&mz search -v -c co64 DJI_20260429201005_0016_D.MP4.mz
DJI_20260429201005_0016_D.MP4.mz: using sidecar DJI_20260429201005_0016_D.MP4.mz.mzs
DJI_20260429201005_0016_D.MP4.mz: search info: matchLen=6 baseTableSize=23 (8388608 entries) long-prefix="co64"
6
DJI_20260429201005_0016_D.MP4.mz took 18ms 844944.4 MB/s
Blocks total: 1814, skipped: 1809 (99.7%), deferred: 0 (0.0%, 0 skipped)
Blocks searched: 5 (0.3%), false positive: 1 (20.0%)
Bytes skipped: 0 compressed, searched: 34007339 uncompressed
Tables: 1814 present, 0 missing, 0 unusable
Table bits/byte: 0.0000, log2: 8.0, avg reductions: 15.0
Table total: 39912 bytes, avg 22 bytes/table, 0.00% of 15208999211 uncompressed
Table population: avg 0.0%, min 0.0%, max 0.4%
Table types: 0 uncompressed (0x45), 1814 compressed (0x46)
Compressed tables: 1814 (100.0% of total), 39912 wire bytes, 58048 uncompressed bitmap bytes (68.76% ratio)
 Sub-blocks: 1814 total (0 tabled, 0 raw, 1810 RLE, 4 sparse); 0 tables emitted (share=0.00 tables/tabled-block)
 Payload bytes: tabled=0 raw=0 RLE=1810 sparse=8; table-header bytes=0

Summary by CodeRabbit

  • Documentation
    • Updated Stream Searching docs with clearer “How It Works” guidance, revised search-table setup examples, and new details on long exact matches and prefix behavior at stream ends.
    • Refined final-block/prefix-only behavior notes for end-of-stream handling.
  • Bug Fixes
    • Improved end-of-stream accuracy by rescanning certain blocks that were previously skipped due to all-zero prefix tables.
    • Adjusted long-prefix handling so prefix-only queries don’t miss matches in the final-block tail.
  • Tests
    • Broadened fuzz coverage and updated expected offset logic for prefix and final-block scenarios.

When searching for the prefix only, an empty table can be used to reject blocks.

Before/after:

```
λ mz sidecar build -search.prefix=co64 DJI_20260429201005_0016_D.MP4.mz

λ mz search -v -c co64 DJI_20260429201005_0016_D.MP4.mz
DJI_20260429201005_0016_D.MP4.mz: using sidecar DJI_20260429201005_0016_D.MP4.mz.mzs
DJI_20260429201005_0016_D.MP4.mz: search info: matchLen=6 baseTableSize=23 (8388608 entries) long-prefix="co64"
6
DJI_20260429201005_0016_D.MP4.mz took 6.522s 2332.0 MB/s
Blocks total: 1814, skipped: 0 (0.0%), deferred: 0 (0.0%, 0 skipped)
Blocks searched: 1814 (100.0%), false positive: 1810 (99.8%)
Bytes skipped: 0 compressed, searched: 15208999211 uncompressed
Tables: 1814 present, 0 missing, 1814 unusable
Table bits/byte: 0.0000, log2: 8.0, avg reductions: 15.0
Table total: 39912 bytes, avg 22 bytes/table, 0.00% of 15208999211 uncompressed
Table population: avg 0.0%, min 0.0%, max 0.0%
Table types: 0 uncompressed (0x45), 1814 compressed (0x46)
Compressed tables: 1814 (100.0% of total), 39912 wire bytes, 58048 uncompressed bitmap bytes (68.76% ratio)
 Sub-blocks: 0 total (0 tabled, 0 raw, 0 RLE, 0 sparse); 0 tables emitted (share=0.00 tables/tabled-block)
 Payload bytes: tabled=0 raw=0 RLE=0 sparse=0; table-header bytes=0

λ go build&&mz search -v -c co64 DJI_20260429201005_0016_D.MP4.mz
DJI_20260429201005_0016_D.MP4.mz: using sidecar DJI_20260429201005_0016_D.MP4.mz.mzs
DJI_20260429201005_0016_D.MP4.mz: search info: matchLen=6 baseTableSize=23 (8388608 entries) long-prefix="co64"
6
DJI_20260429201005_0016_D.MP4.mz took 18ms 844944.4 MB/s
Blocks total: 1814, skipped: 1809 (99.7%), deferred: 0 (0.0%, 0 skipped)
Blocks searched: 5 (0.3%), false positive: 1 (20.0%)
Bytes skipped: 0 compressed, searched: 34007339 uncompressed
Tables: 1814 present, 0 missing, 0 unusable
Table bits/byte: 0.0000, log2: 8.0, avg reductions: 15.0
Table total: 39912 bytes, avg 22 bytes/table, 0.00% of 15208999211 uncompressed
Table population: avg 0.0%, min 0.0%, max 0.4%
Table types: 0 uncompressed (0x45), 1814 compressed (0x46)
Compressed tables: 1814 (100.0% of total), 39912 wire bytes, 58048 uncompressed bitmap bytes (68.76% ratio)
 Sub-blocks: 1814 total (0 tabled, 0 raw, 1810 RLE, 4 sparse); 0 tables emitted (share=0.00 tables/tabled-block)
 Payload bytes: tabled=0 raw=0 RLE=1810 sparse=8; table-header bytes=0
```
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds tail-rescue handling for all-zero prefix-table skips at stream ends, updates long-prefix matching rules, extends fuzz coverage, and documents the final-block scan behavior.

Changes

Tail Rescue for Final-Block Prefix-Table Skips

Layer / File(s) Summary
Spec and docs: final-block scan rule and long-prefix behavior
SPEC_SEARCH.md, SEARCH.md
SPEC_SEARCH.md adds the final-block scan rule for prefix-only queries. SEARCH.md updates the search explanation, prefix-byte guidance, long exact match guidance, and the SearchTableConfig API table.
tableAllZero helper in search_table.go
search_table.go
Adds tableAllZero([]byte) bool to detect all-zero tables.
patternCanUseConfig and patternCanMatch long-prefix logic
search_reader.go
Refactors long-prefix usability and matching behavior so all-zero long-prefix tables defer correctness to EOF tail scanning.
BlockSearcher tail-rescue state, skip recording, and rescueTail
search_reader.go
Adds tail-rescue state, records all-zero-table skips for later rescanning, and rescans buffered blocks at EOF and stream boundaries.
SidecarSearcher tail-rescue state, blockDecision emptySkip, and rescueTail
sidecar_search.go
Adds tail-rescue state and emptySkip, records skipped block metadata, and rescans held-back blocks during finalization and stream transitions.
FuzzSearchRoundtrip prefix-only coverage
search_test.go
Adds a fuzz seed and expectation path for prefix-only EOF-tail behavior.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • minio/minlz#44: Changes prefix-index and end-of-stream behavior around missed matches at block ends, which is directly related to this PR’s final-block tail rescue.
  • minio/minlz#44: Updates the same search-boundary behavior that this PR extends to all-zero prefix tables and prefix-only queries.

Suggested reviewers

  • grahit13
  • krisis

🐇 A zero table slept at stream-end’s gate,
Then EOF whispered, “I’m your fate.”
Tail rescue hopped in, neat and bright,
And found the match before last light.
Ears up, little blocks — the bunny’s in flight.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding support for prefix-only search behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@search_reader.go`:
- Around line 1449-1462: The byte-/mask-prefix handling in the search matcher is
still blocking short prefix-only queries by returning false before any prefix
bitmap logic runs. Update the searchTableTypeBytePrefix and
searchTableTypeMaskPrefix branches in search_reader.go so they follow the
SPEC_SEARCH.md final-block behavior for table types 2/3/4: allow the matcher to
decode and evaluate short patterns, and apply the same empty-table/tail fallback
used by the long-prefix path. If this support is not intended, narrow the spec
instead of keeping the current gate in the matching logic.

In `@SEARCH.md`:
- Around line 191-196: The JSON prefix guidance in the search heuristics is too
absolute and should be softened. Update the wording in the section about picking
bytes before search values, using the same JSON-related guidance point as the
anchor, so it reads as a common heuristic for JSON strings/fields rather than
claiming values always follow specific patterns like `":` or `:[`. Keep the
examples focused on typical anchors such as quotes and colons, but avoid
universal language that could mislead users about arrays, commas, or whitespace
in pretty-printed JSON.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 82d2f183-2053-4807-93b3-a41c58655ad3

📥 Commits

Reviewing files that changed from the base of the PR and between 7fcdc05 and e2a4129.

📒 Files selected for processing (6)
  • SEARCH.md
  • SPEC_SEARCH.md
  • search_reader.go
  • search_table.go
  • search_test.go
  • sidecar_search.go

Comment thread search_reader.go
Comment thread SEARCH.md Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
SEARCH.md (1)

189-197: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Soften the JSON prefix guidance.

Line 193 still claims values "always follow ": or :[" — this is too absolute and misleading for arrays, commas, and pretty-printed JSON with whitespace. Please reword as a common heuristic. This was flagged in a previous review and remains unaddressed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@SEARCH.md` around lines 189 - 197, The JSON prefix guidance is too absolute
in the “Choosing good prefix bytes” section; reword the dense JSON bullet in
SEARCH.md to describe `"` and `:` as a common heuristic rather than saying
values always follow `":` or `:[`. Update the wording in that bullet to account
for arrays, commas, and pretty-printed JSON with whitespace while keeping the
prefix-bytes advice concise and practical.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@SEARCH.md`:
- Around line 189-197: The JSON prefix guidance is too absolute in the “Choosing
good prefix bytes” section; reword the dense JSON bullet in SEARCH.md to
describe `"` and `:` as a common heuristic rather than saying values always
follow `":` or `:[`. Update the wording in that bullet to account for arrays,
commas, and pretty-printed JSON with whitespace while keeping the prefix-bytes
advice concise and practical.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: cfbc82d6-168d-4a77-9f2f-f217f1548005

📥 Commits

Reviewing files that changed from the base of the PR and between e2a4129 and 7764d1f.

📒 Files selected for processing (1)
  • SEARCH.md

@klauspost klauspost merged commit cc484d6 into minio:main Jun 30, 2026
59 checks passed
@klauspost klauspost deleted the prefix-only-search branch June 30, 2026 12:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant