Skip to main content

Vector and Full-Text Search Benchmark

Query latency and throughput of vector search and full-text search on 10 million rows, top 10 results. All datasets are public. You can run the SQL on this page to get the same setup.

Test Environment​

ItemValue
WarehouseSmall, one cluster, default settings, AWS us-east-2
ClientSame region, AWS PrivateLink, HTTP Query API
Latency8 QPS. Client: request sent to all rows received. Server: time in the warehouse.
Throughput4–48 concurrent clients, warm cache
Warm cacheThe cache is full before the test
Cold cacheThe cache is empty at the start of the test
Recall@10Overlap with the exact top 10 of a full scan

Latency​

Unit: ms. 480 requests, 0 errors.

CacheLatencyp50p90p99Recall@10
WarmClient40.843.253.394.6%
WarmServer27282994.6%
Cold (est.)Client47269578594.6%
Cold (est.)Server45868076094.6%
note

The cold values are estimates. The vector index is in memory, and the result rows come from object storage.

Throughput​

Small warehouse, one cluster. Unit: ms (client). 1,000 query vectors, 0 errors.

ConcurrencyQPSp50p90p99
471.246.252.258.9
698.650.558.067.5
8117.057.368.378.1
10141.759.977.294.6
12137.076.895.8115.3
tip

Above 12 concurrent clients, QPS stays at approximately 120–125 and latency increases. For more QPS, enable Multi-Cluster or use a larger warehouse.

Dataset​

ItemValue
SourceWikipedia 2023-11 (en), files 0000–0099
Rows10,000,000 × 1024-dim float32 (Cohere embed-multilingual-v3)
Size41.0 GB raw → 19.4 GB data + 7.5 GB HNSW index
IndexHNSW, cosine, m = 32, ef_construct = 200
Queries1,000 vectors from file 0100 (not in the table)

Load and Query​

Download the files with the Hugging Face CLI, and upload them to a stage with BendSQL:

# 1. Download files 0000–0100 (approximately 22 GB)
hf download CohereLabs/wikipedia-2023-11-embed-multilingual-v3 --repo-type dataset \
--revision ade45fb52bd549f5e8c065636fe4160a43c2af36 \
--include "en/00*.parquet" "en/0100.parquet" --local-dir /data/wiki

# 2. Upload the files to a stage
bendsql --query "CREATE STAGE wiki_stage FILE_FORMAT = (TYPE = PARQUET)"
bendsql --query "PUT fs:///data/wiki/en/*.parquet @wiki_stage/"
-- 3. Table with a vector index
CREATE TABLE vec_10m (
id BIGINT,
emb VECTOR(1024),
VECTOR INDEX vidx (emb) distance = 'cosine' m = 32 ef_construct = 200
);

-- 4. Load files 0000–0099 (10,000,000 rows). Hash the string _id to BIGINT.
COPY INTO vec_10m
FROM (SELECT xxhash64(_id) >> 1, emb FROM @wiki_stage)
PATTERN = '00[0-9][0-9][.]parquet';

-- 5. Query vectors from file 0100
CREATE TABLE vec_queries AS
SELECT _id, emb::VECTOR(1024) AS emb
FROM @wiki_stage/0100.parquet
LIMIT 1000;

-- 6. Top 10 query. Use a vector from vec_queries.
SELECT id, cosine_distance(emb, [0.0123, -0.0456, ...]::VECTOR(1024)) AS distance
FROM vec_10m
ORDER BY distance ASC
LIMIT 10;

Latency​

Unit: ms. 1,677 queries, 0 errors.

CacheLatencyp50p90p99
WarmClient34.540.552.7
WarmServer212638
ColdClient35.699.2253.1
ColdServer2285229

Throughput​

Small warehouse, one cluster. Unit: ms (client). 1,677 queries, 0 errors.

ConcurrencyQPSp50p90p99
482.438.145.257.5
6109.643.355.471.8
8120.053.872.190.1
10127.267.485.3103.4
12128.082.2101.0132.2
tip

Above 12 concurrent clients, QPS stays at approximately 120–125 and latency increases. For more QPS, enable Multi-Cluster or use a larger warehouse.

Dataset​

ItemValue
SourceMS MARCO v2.1 passages, shards 00–05
Rows10,000,000 passages, 990 bytes average
Size9.9 GB raw → 2.1 GB data + 3.5 GB inverted index
Queries1,677 TREC 2021–2023 queries

Load and Query​

# 1. Download shards 00–05 and the queries (approximately 26 GB)
hf download CohereLabs/msmarco-v2.1-embed-english-v3 --repo-type dataset \
--revision e78737fe92ac1b783211b705c12207ca75fcc9b7 \
--include "passages_parquet/*segmented_0[0-5].parquet" "queries_parquet/queries.parquet" \
--local-dir /data/msmarco

# 2. Upload the files to a stage
bendsql --query "CREATE STAGE msmarco_stage FILE_FORMAT = (TYPE = PARQUET)"
bendsql --query "PUT fs:///data/msmarco/*/*.parquet @msmarco_stage/"
-- 3. Table with an inverted index
CREATE TABLE fts_10m (
id VARCHAR,
text VARCHAR,
INVERTED INDEX idx_text (text)
);

-- 4. Load shards 00–04 (9,511,868 rows), then 488,132 rows of shard 05
COPY INTO fts_10m
FROM (SELECT docid, segment FROM @msmarco_stage)
PATTERN = '.*segmented_0[0-4][.]parquet';

INSERT INTO fts_10m
SELECT docid, segment
FROM @msmarco_stage/msmarco_v2.1_doc_segmented_05.parquet
LIMIT 488132;

-- 5. Queries
CREATE TABLE fts_queries AS
SELECT _id, text
FROM @msmarco_stage/queries.parquet;

-- 6. Top 10 query. Use a text from fts_queries in lowercase,
-- with special characters escaped by a backslash (\).
SELECT id, score() AS score
FROM fts_10m
WHERE MATCH(text, 'what is produced by muscle', 'operator=or')
ORDER BY score DESC
LIMIT 10;
Vector Query10M docs
p50
40.8ms
p90
43.2ms
p99
53.3ms
Client latencyDatabend CloudDatabend Cloud
Full-Text Query10M docs
p50
34.5ms
p90
40.5ms
p99
52.7ms
Client latencyDatabend CloudDatabend Cloud