pingcap / pingcap/tiflash

Inconsistent results between tikv and tiflash when performing vector search

Open
#10,077 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

component/storage impact/inconsistency may-affects-6.1 may-affects-6.5 may-affects-7.1 may-affects-7.5 may-affects-8.1 may-affects-8.5 severity/major type/bug
Dominant language
C++
Stars
1k
Forks
423
Avg merge
1d 15h
Merged PRs (30d)
24

Description

Bug Report

Currently, vector index is only built in tiflash. When we perform vector search, if the plan chooses to follow the tiflash path, tidb will directly use the distance calculated in tiflash for sorting. If the plan chooses to follow the tikv path, after tikv calculates the distance, tidb will still perform another distance calculation and sort based on this result. At this time, since tiflash calculates the distance by calling the optimized calculation of the SIMD library, the direct calculation method of tidb will produce different results, so the tikv and tiflash paths will produce different results.

mysql> explain select /*+ read_from_storage(tikv[t1]) */ id from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10;
+--------------------------------+---------+-----------+---------------+------------------------------------------------------------------------------+
| id                             | estRows | task      | access object | operator info                                                                |
+--------------------------------+---------+-----------+---------------+------------------------------------------------------------------------------+
| Projection_15                  | 10.00   | root      |               | test.t1.id                                                                   |
| └─TopN_8                       | 10.00   | root      |               | Column#4, offset:0, count:10                                                 |
|   └─Projection_16              | 10.00   | root      |               | test.t1.id, test.t1.vec, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#4 |
|     └─TableReader_14           | 10.00   | root      |               | data:TopN_13                                                                 |
|       └─TopN_13                | 10.00   | cop[tikv] |               | vec_cosine_distance(test.t1.vec, [1,1,1]), offset:0, count:10                |
|         └─TableFullScan_12     | 100.00  | cop[tikv] | table:t1      | keep order:false, stats:pseudo                                               |
+--------------------------------+---------+-----------+---------------+------------------------------------------------------------------------------+
6 rows in set (0.01 sec)

mysql>  explain select /*+ read_from_storage(tiflash[t1]) */ id from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10;
+--------------------------------+---------+--------------+---------------+-----------------------------------------------------------------+
| id                             | estRows | task         | access object | operator info                                                   |
+--------------------------------+---------+--------------+---------------+-----------------------------------------------------------------+
| TopN_10                        | 10.00   | root         |               | Column#7, offset:0, count:10                                    |
| └─TableReader_21               | 10.00   | root         |               | MppVersion: 2, data:ExchangeSender_20                           |
|   └─ExchangeSender_20          | 10.00   | mpp[tiflash] |               | ExchangeType: PassThrough                                       |
|     └─TopN_19                  | 10.00   | mpp[tiflash] |               | Column#7, offset:0, count:10                                    |
|       └─Projection_18          | 10.00   | mpp[tiflash] |               | test.t1.id, vec_cosine_distance(test.t1.vec, [1,1,1])->Column#7 |
|         └─TableFullScan_17     | 100.00  | mpp[tiflash] | table:t1      | keep order:false, stats:pseudo                                  |
+--------------------------------+---------+--------------+---------------+-----------------------------------------------------------------+
6 rows in set (0.00 sec)
1. Minimal reproduce step (Required)
CREATE TABLE t1 (
    id INT PRIMARY KEY,
    vec VECTOR(3),
    VECTOR INDEX idx_vec ((VEC_COSINE_DISTANCE(vec)))
);

INSERT INTO t1 (id, vec)
WITH RECURSIVE numbers(n) AS (
    SELECT 1
    UNION ALL
    SELECT n + 1 FROM numbers WHERE n < 100
)
SELECT 
    n AS id,
    CONCAT('[', RAND(), ',', RAND(), ',', RAND(), ']') AS vec
FROM numbers;

alter table t1 compact;

select /*+ read_from_storage(tikv[t1]) */ id from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10;
+-----+
| id  |
+-----+
|  16 |
|  67 |
|  59 |
|  28 |
|  94 |
|  26 |
|  53 |
|  65 |
| 100 |
|  31 |
+-----+
10 rows in set (0.02 sec)

select /*+ read_from_storage(tiflash[t1]) */ id from t1 order by vec_cosine_distance(vec, '[1,1,1]') limit 10;
+-----+
| id  |
+-----+
|  59 |
|  16 |
|  53 |
|  67 |
|  28 |
|  65 |
|  94 |
|  31 |
|  26 |
| 100 |
+-----+
10 rows in set (0.01 sec)
2. What did you expect to see? (Required)

Same results

3. What did you see instead (Required)

different results

4. What is your TiFlash version? (Required)

tidb-cse: release-7.5-keyspace
tiflash-cse: cloud-engine-on-release-8.5
tikv-cse: cloud-engine

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the SQL reproduction and EXPLAIN plans comparing the forced tikv and tiflash paths. Trace how each path calculates and sorts vec_cosine_distance results, then verify the fix by running the provided dataset and confirming both paths return the same top 10 ids.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
databases, search
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.