Skip to content

ai: add Hybrid Search with SQL, full-text plus vector search in one query - #24202

Merged
ti-chi-bot[bot] merged 6 commits into
release-8.5from
hybrid-search-sql-guide-2026-10
Oct 14, 2026
Merged

ti-chi-bot[bot] merged 6 commits into
release-8.5from
hybrid-search-sql-guide-2026-10

Conversation

@seominjea1942

@seominjea1942 seominjea1942 commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

What is changed, added or deleted? (Required)

Adds ai/guides/vector-search-hybrid-search-sql.md, "Hybrid Search with SQL". The existing Hybrid Search guide uses the pytidb SDK, which fuses the two result lists in Python, and says you "can perform a search using SQL directly" without showing how. This page shows it: one table with an Auto Embedding column, a full-text index, and a vector index; vector search by text; full-text search; and both merged with Reciprocal Rank Fusion in a single SQL statement. It mirrors the existing "Full-Text Search with SQL" and "Full-Text Search with Python" pair.

Also proposes one TOC-ai.md line under Hybrid Search. The Doc team decides placement.

Also adds one sentence to the existing Hybrid Search guide (ai/guides/vector-search-hybrid-search.md), where it already says you "can perform a search using SQL directly", linking to the new page.

Measured on TiDB Cloud Starter, 8.0.11-TiDB-v8.5.3-serverless, AWS Oregon (us-west-2), 2026-10-06. Every SQL block was run verbatim and in order on a fresh database, with no statements in between, and each output table on the page is copied from that run. EXPLAIN on the Step 5 query shows annIndex: on the vector search and textSearch:(top20 ...) on the full-text search, so the plan uses both indexes. On a table this small the indexes had not been built yet (information_schema.tiflash_indexes reported no indexed stable rows), so "uses" here means the optimizer chose the index, not that rows were served from a built index.

Reviewer note on the READ_FROM_STORAGE(TIFLASH[docs]) hint in Step 5. On a 6-row table, whether the optimizer used the vector index without the hint depended on the statistics state. Right after insert, with pseudo statistics, it used the index for both the Step 3 query and the Step 5 subquery. Once a real row count was recorded, an independent review saw it read from TiKV and skip the vector index for both, the top-level Step 3 query included. With the hint, every plan used both indexes. The page explains the hint and says it applies to any vector search on a small table. If the vector search owners prefer a different recommendation, the hint is the line to change.

The same review saw full-text scores change a few minutes after ANALYZE TABLE, once TiFlash moved the rows to its stable layer. With the original query text, the filler word "on" then let an unrelated row move up in the full-text ranking. I could not reproduce that shift in a second run, so the page now uses a query without filler words and adds a sentence saying scores can change on a freshly loaded table, which can reorder rows with similar scores. The new query gave the page's output in every run, but none of those runs reproduced the shift, so it is not proven to hold after one. In the review's shifted state the old query matched an unrelated row only through the word "on", which the new query does not contain.

The availability wording in Prerequisites matches the existing Hybrid Search guide and Auto Embedding overview, except that "we are continuously rolling it out" became "is being rolled out", following the writing style guide's rule against "we".

Which TiDB version(s) do your changes apply to? (Required)

  • master (the latest development version)
  • v8.5 (TiDB 8.5 versions)

What is the related PR or file link(s)?

AI agent involvement

  • The changes in this PR were primarily made by an AI agent on behalf of the PR author.

The text and the measurements were produced by an AI agent (Claude). I reviewed the changes and the evidence before opening this PR.

Do your changes match any of the following descriptions?

  • Delete files
  • Change aliases
  • Need modification after applied to another branch
  • Might cause conflicts after applied to another branch

Summary by CodeRabbit

  • Documentation
    • Added a tutorial for performing hybrid search in SQL, covering vector and keyword searches, combining rankings, and checking index usage.
    • Added links to the SQL tutorial from the guides table of contents and the existing hybrid search tutorial.
    • Clarified the existing Python guide’s title in the table of contents.

@ti-chi-bot ti-chi-bot Bot added contribution This PR is from a community contributor. missing-translation-status This PR does not have translation status info. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Oct 7, 2026
@coderabbitai

coderabbitai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: pingcap/docs/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: d5f962d4-317f-4660-83ce-2d066fae9af4
📥 Commits

Reviewing files that changed from the base of the PR and between bc1671e and 43b9794.

📒 Files selected for processing: 1
  • ai/guides/vector-search-hybrid-search-sql.md

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 1 remain after this review.

📝 Walkthrough

Adds a SQL tutorial for hybrid search in TiDB Cloud. The tutorial covers vector and full-text queries, combines their rankings with Reciprocal Rank Fusion, and describes TiFlash index checks. Links to the tutorial are added to the AI table of contents and the existing hybrid-search guide.

Changes: SQL Hybrid Search Guide

Layer / File(s) Summary
Set up and run SQL searches
ai/guides/vector-search-hybrid-search-sql.md
Documents prerequisites, table and index setup, embedding insertion, and separate vector and full-text search queries.
Combine rankings and link the guide
ai/guides/vector-search-hybrid-search-sql.md, TOC-ai.md, ai/guides/vector-search-hybrid-search.md
Documents Reciprocal Rank Fusion over up to 20 candidates per search, TiFlash rank changes, routing hints, and index checks with EXPLAIN. Adds links to the SQL guide and renames the existing table-of-contents link to “Hybrid Search via Python.”

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Other

Suggested reviewers: qiancai

Merge Risk: ⚪ Minimal · up to 43b97

The guide’s setup and embedding dimensions match the documented Starter environment, and the earlier full-scan query shape has been replaced. No material merge risk remains beyond normal checks.

### Architecture Summary

Architecture risk: 🔵 Low · up to 43b97

The change affects 2 systems.

Changed systems: ai, TOC-ai.md

Architecture concerns
No architecture-level concerns identified.

Review details

Systems and components

  • observed — ai (service) was modified; 2 changed files map to changed impact.
  • observed — TOC-ai.md (service) was modified; 1 changed file maps to changed impact.

Before / after behavior

  • observed — Modified behavior in TOC-ai.md: Renamed the Hybrid Search link from “Hybrid Search Guide” to “Hybrid Search via Python” and added a link to the Hybrid Search via SQL page.
  • observed — Modified behavior in ai/guides/vector-search-hybrid-search.md: Added a link to the SQL hybrid search guide; the existing introduction text is unchanged.
  • observed — Modified behavior in ai/guides/vector-search-hybrid-search-sql.md: Adds the tutorial title, overview, and prerequisites: full-text search is available on Starter in the listed AWS regions, while Auto Embedding is available on AWS-hosted Starter instances.
  • observed — Modified behavior in ai/guides/vector-search-hybrid-search-sql.md: Adds SQL to create docs with a stored 1024-dimensional vector generated from content using TiDB Cloud’s embedding model, alongside full-text and cosine-distance vector indexes; notes the model dimension requirement.
Pre-merge checks: Passed 5
Passed Passed checks: 5 passed
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main change: adding SQL-based hybrid search with full-text and vector search in one query.
Description check Passed The description covers the required change summary, affected TiDB version, reference link, AI involvement, and change-category checklist. It also provides detailed testing and reviewer context.
Docstring Coverage Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 0…
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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: 1


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Repository: pingcap/docs/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 9f464575-05a6-454b-b4bb-794cbcab0def
📥 Commits

Reviewing files that changed from the base of the PR and between 49ed15d and 088a203.

📒 Files selected for processing (3)
  • TOC-ai.md
  • ai/guides/vector-search-hybrid-search-sql.md
  • ai/guides/vector-search-hybrid-search.md

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 2 remain after this review.

Comment thread ai/guides/vector-search-hybrid-search.md Outdated
@qiancai qiancai self-assigned this Oct 8, 2026
@qiancai qiancai added translation/no-need No need to translate this PR. area/tidb-cloud This PR relates to the area of TiDB Cloud. labels Oct 8, 2026
@ti-chi-bot ti-chi-bot Bot removed the missing-translation-status This PR does not have translation status info. label Oct 8, 2026

@qiancai qiancai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Rest LGTM

Comment thread ai/guides/vector-search-hybrid-search-sql.md
Comment thread TOC-ai.md Outdated
Comment thread ai/guides/vector-search-hybrid-search-sql.md Outdated
Comment thread ai/guides/vector-search-hybrid-search-sql.md Outdated
Comment thread ai/guides/vector-search-hybrid-search.md Outdated
Comment thread ai/guides/vector-search-hybrid-search-sql.md Outdated
@ti-chi-bot ti-chi-bot Bot added the needs-1-more-lgtm Indicates a PR needs 1 more LGTM. label Oct 8, 2026
@ti-chi-bot

ti-chi-bot Bot commented Oct 8, 2026

Copy link
Copy Markdown

[LGTM Timeline notifier]

Timeline:

  • 2026-10-08 06:43:30.964021972 +0000 UTC m=+281420.711252861: ☑️ agreed by qiancai.

Comment thread ai/guides/vector-search-hybrid-search-sql.md
@qiancai qiancai removed the area/tidb-cloud This PR relates to the area of TiDB Cloud. label Oct 8, 2026

The following query runs both searches, ranks each result list, and merges them with Reciprocal Rank Fusion (RRF). Each row scores `1 / (60 + rank)` for every list it appears in, and the scores are added. A row that ranks well in both lists rises to the top. The constant `60` is the value commonly used for RRF; a larger value reduces the advantage of top-ranked rows over lower-ranked ones.

```sql

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The outer query starts from docs and LEFT JOINs the two Top-K result sets:

FROM docs d
LEFT JOIN vec ON vec.id = d.id
LEFT JOIN fts ON fts.id = d.id

Although both search branches return at most 20 candidates, the outer query might still scan the entire docs table before filtering out non-matching rows.

This could become a significant performance bottleneck on large datasets, even when both search branches use their respective indexes.

I suggest rewriting the SQL as follows:

WITH
vec AS (
  SELECT id,
         ROW_NUMBER() OVER (ORDER BY distance, id) AS r
  FROM (
    SELECT /*+ READ_FROM_STORAGE(TIFLASH[docs]) */
           id,
           VEC_EMBED_COSINE_DISTANCE(
             content_vector,
             'vector index error 8200 partitioned table'
           ) AS distance
    FROM docs
    ORDER BY distance
    LIMIT 20
  ) v
),
fts AS (
  SELECT id,
         ROW_NUMBER() OVER (ORDER BY score DESC, id) AS r
  FROM (
    SELECT id,
           fts_match_word(
             'vector index error 8200 partitioned table',
             content
           ) AS score
    FROM docs
    WHERE fts_match_word(
      'vector index error 8200 partitioned table',
      content
    )
    ORDER BY score DESC
    LIMIT 20
  ) f
),
hits AS (
  SELECT id,
         1.0 / (60 + r) AS contribution,
         r AS vector_rank,
         NULL AS fulltext_rank
  FROM vec
  UNION ALL
  SELECT id,
         1.0 / (60 + r),
         NULL,
         r
  FROM fts
),
top_hits AS (
  SELECT id,
         SUM(contribution) AS rrf_score,
         MAX(vector_rank) AS vector_rank,
         MAX(fulltext_rank) AS fulltext_rank
  FROM hits
  GROUP BY id
  ORDER BY rrf_score DESC, id
  LIMIT 3
)
SELECT d.id, d.content,
       t.rrf_score,
       t.vector_rank,
       t.fulltext_rank
FROM top_hits t
JOIN docs d ON d.id = t.id
ORDER BY t.rrf_score DESC, t.id;

With this approach, the RRF fusion operates on at most 40 candidate rows. The final Top-K selection is performed logically before joining back to docs to retrieve document content.

This avoids the need to use the full docs table as the driving input for fusion.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@JinheLin Good point. I’ve updated Step 5 to first fuse the bounded Top-K candidate IDs from the vector and full-text branches, and then join back to docs only in the final step to fetch the document content.

PTAL at the changes here:
0144f88

@zhaoshangzi zhaoshangzi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@ti-chi-bot

ti-chi-bot Bot commented Oct 10, 2026

Copy link
Copy Markdown

@zhaoshangzi: adding LGTM is restricted to approvers and reviewers in OWNERS files.

Details

In response to this:

LGTM

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@qiancai
qiancai requested a review from yongman October 10, 2026 07:55
@ti-chi-bot

ti-chi-bot Bot commented Oct 10, 2026

Copy link
Copy Markdown

@yongman: adding LGTM is restricted to approvers and reviewers in OWNERS files.

Details

In response to this:

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

Comment thread ai/guides/vector-search-hybrid-search-sql.md Outdated
Comment thread ai/guides/vector-search-hybrid-search-sql.md Outdated
Comment thread ai/guides/vector-search-hybrid-search-sql.md Outdated
@ti-chi-bot

ti-chi-bot Bot commented Oct 14, 2026

Copy link
Copy Markdown

@JinheLin: adding LGTM is restricted to approvers and reviewers in OWNERS files.

Details

In response to this:

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

`WHERE fts_match_word(...) > 0` fails with ERROR 1221, because TiDB requires
fts_match_word() to appear on its own in the WHERE clause. Without `> 0`, the
query runs, uses both the vector index and the full-text index, and returns
the documented output (verified on TiDB v8.5.3-serverless).
@ti-chi-bot

ti-chi-bot Bot commented Oct 14, 2026

Copy link
Copy Markdown

@qiancai: Your lgtm message is repeated, so it is ignored.

Details

In response to this:

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@qiancai

qiancai commented Oct 14, 2026

Copy link
Copy Markdown
Collaborator

/approve

@qiancai qiancai added the lgtm label Oct 14, 2026
@ti-chi-bot

ti-chi-bot Bot commented Oct 14, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: qiancai

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@ti-chi-bot ti-chi-bot Bot added the approved label Oct 14, 2026
@ti-chi-bot
ti-chi-bot Bot merged commit 6ce0b6a into release-8.5 Oct 14, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved contribution This PR is from a community contributor. lgtm needs-1-more-lgtm Indicates a PR needs 1 more LGTM. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. translation/no-need No need to translate this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants