Skip to content

Collections and indexes

Collection declarations make vector topology reviewable alongside the queries that use it. Define vectors first, add payload indexes for fields you filter or order by, and add shard keys only when Qdrant routing is part of the design.

Vector names are application-defined. dense, sparse, and colbert are useful conventions, but vector configuration determines the actual role. A dense definition is name VECTOR(size, distance) with distance COSINE, DOT, EUCLID, or MANHATTAN; a sparse definition is name SPARSE with optional WITH SPARSE (...) / WITH INDEX (...) config. Dense vectors may also set a storage datatype (float32, float16, uint8, or turbo4 for TurboQuant 4-bit) and a memory placement.

QQLDense, sparse, and multivector topologyTry in playground
CREATE COLLECTION research (
dense VECTOR(384, COSINE),
colbert VECTOR(128, COSINE) WITH HNSW (m = 0) WITH MULTIVECTOR (comparator = 'max_sim'),
sparse SPARSE
)
WITH HNSW (m = 16, ef_construct = 100);
RequirementSchema choice
Semantic retrievalA dense VECTOR(size, distance)
Lexical or sparse retrievalA named SPARSE vector
Late interactionA multivector with a comparator
Hybrid retrievalBoth a dense and sparse vector

A CREATE COLLECTION can name a mode instead of (or alongside) explicit vector definitions. Modes infer a conventional topology:

ModeResulting topology
(no mode)Bare dense topology without a model hint
USING DENSE MODEL 'name'Dense topology with dimension inference from the model
USING HYBRIDConventional hybrid dense + sparse topology
HYBRID RERANKConventional rerank topology
HYBRID DENSE VECTOR semantic_v2 SPARSE VECTOR lexical_v2Hybrid topology with arbitrary role names

Explicit dense and sparse vector definitions may coexist with the collection blocks below. Dense size must be positive.

Config blocks attach to the collection with WITH <BLOCK> (...) and to individual dense vectors (WITH HNSW, WITH VECTOR, WITH QUANTIZATION, WITH MULTIVECTOR). Keys are ASCII case-insensitive and unique.

BlockAccepted keys
HNSWm, ef_construct, full_scan_threshold, max_indexing_threads, on_disk, payload_m, inline_storage, memory (cold/cached/pinned)
VECTORon_disk, memory (cold/cached/pinned), datatype (float32/float16/uint8/turbo4)
OPTIMIZERSdeleted_threshold, vacuum_min_vector_number, default_segment_number, max_segment_size, memmap_threshold, indexing_threshold, flush_interval_sec, max_optimization_threads, prevent_unoptimized
PARAMSreplication_factor, write_consistency_factor, on_disk_payload, payload_memory (cold/cached only), shard_number, sharding_method, shard_keys, read_fan_out_factor, read_fan_out_delay_ms
QUANTIZATIONtype (scalar/binary/product/turbo), disabled, always_ram, quantile, bits, compression, encoding, query_encoding, memory
WALwal_capacity_mb, wal_segments_ahead, wal_retain_closed (create only)
STRICT_MODEenabled, max_query_limit, max_timeout, search_allow_exact, search_max_oversampling, and the remaining StrictModeConfig keys
METADATAFree-form string keys with any JSON value
MULTIVECTORcomparator (max_sim)
sparse INDEX/SPARSEmodifier, full_scan_threshold, on_disk, datatype (float32/float16/uint8; not turbo4), memory

read_fan_out_factor and read_fan_out_delay_ms parse on CREATE and ALTER: create-time values apply with a follow-up PATCH, since the create wire shape carries no fan-out fields. QUANTIZATION (disabled = true) is an ALTER form. WITH WAL is create-only. ALTER COLLECTION applies any of the HNSW, VECTOR, OPTIMIZERS, PARAMS, QUANTIZATION, STRICT_MODE, or METADATA blocks to an existing collection.

ALTER also accepts per-vector diffs. The named dense form is WITH VECTOR <name> (<nested blocks>) with HNSW (...), QUANTIZATION (...), or VECTOR (...) blocks — comma-separated, each at most once. The unnamed WITH VECTOR (...) form targets the default unnamed vector. Sparse vectors use WITH SPARSE <name> (SPARSE (...) | INDEX (...)). Every block is field-wise: unset keys keep their current value. datatype has no per-vector diff field on the Qdrant wire and is rejected (QQL-PARSE-VECTOR-DIFF); duplicate vector names, duplicate nested blocks, and empty blocks are rejected too. Diff names are validated against the collection schema before the update is sent (QQL-UNKNOWN-VECTOR when the vector does not exist).

QQLPer-vector ALTER diffsTry in playground
ALTER COLLECTION docs
WITH VECTOR dense (
HNSW (m = 32, memory = 'cold'),
QUANTIZATION (type = 'scalar', quantile = 0.99),
VECTOR (memory = 'cached', on_disk = true)
);
ALTER COLLECTION docs WITH VECTOR colbert (QUANTIZATION (disabled = true));
ALTER COLLECTION docs
WITH SPARSE bm25 (SPARSE (modifier = 'idf', full_scan_threshold = 5000, datatype = 'float16'));

memory controls how a component is held in RAM while data remains on disk: cold (load on demand), cached (OS page cache), or pinned (keep resident). payload_memory is the payload counterpart under WITH PARAMS and accepts only cold or cachedpinned is rejected for payload. Prefer memory / payload_memory for new scripts; legacy on_disk / on_disk_payload / always_ram still parse and dual-write through 1.19.

QQLMemory placement and turbo4 datatypeTry in playground
CREATE COLLECTION docs (
dense VECTOR(384, COSINE) WITH VECTOR (memory = 'cached', datatype = 'turbo4')
)
WITH HNSW (memory = 'cold')
WITH PARAMS (payload_memory = 'cold');
CREATE COLLECTION docs2 (
sparse SPARSE WITH SPARSE (modifier = 'idf', memory = 'cached')
);
CREATE COLLECTION docs3 (
dense VECTOR(128, DOT) WITH QUANTIZATION (type = 'scalar', memory = 'pinned')
);
QQLReplication, quantization, and alterTry in playground
CREATE COLLECTION sec10k (
dense VECTOR(768, COSINE),
sparse SPARSE
)
WITH HNSW (m = 16, ef_construct = 100)
WITH PARAMS (replication_factor = 2, shard_number = 8, sharding_method = 'custom', shard_keys = ['honeywell', 'ge']);
ALTER COLLECTION sec10k WITH QUANTIZATION (type = 'scalar');
QQLWAL, strict mode, and metadataTry in playground
CREATE COLLECTION docs (v VECTOR(8, COSINE)) WITH WAL (wal_capacity_mb = 32, wal_segments_ahead = 2, wal_retain_closed = 1);
CREATE COLLECTION docs (v VECTOR(8, COSINE)) WITH STRICT_MODE (enabled = true, max_query_limit = 100);
CREATE COLLECTION docs (v VECTOR(8, COSINE)) WITH METADATA (owner = 'team', version = 3);
ALTER COLLECTION docs WITH STRICT_MODE (enabled = false);
ALTER COLLECTION docs WITH METADATA (owner = 'team');

Create payload indexes for fields used frequently in filters, tenant predicates, or ordering. Index design is a Qdrant performance decision, not a requirement for every payload field. The index TYPE is keyword, integer, float, geo, text, bool, datetime, or uuid.

QQLTenant, prefix, and text payload indexesTry in playground
CREATE INDEX ON COLLECTION research FOR tenant_id TYPE keyword WITH (is_tenant = true, on_disk = true);
CREATE INDEX ON COLLECTION research FOR title TYPE keyword WITH (prefix = true, memory = 'cached');
CREATE INDEX ON COLLECTION research FOR content TYPE text WITH (tokenizer = 'multilingual', lowercase = true, phrase_matching = true);
CREATE INDEX ON COLLECTION research FOR body TYPE text WITH (stopwords = 'english');
CREATE INDEX ON COLLECTION research FOR body TYPE text WITH (stopwords = {languages: ['english'], custom: ['foo']});

CREATE INDEX ... WITH (...) accepts the following options:

OptionType
is_tenant, on_disk, enable_hnswboolean
lowercase, ascii_folding, phrase_matching, lookup, range, is_principal, prefixboolean
min_token_len, max_token_lennon-negative integer
tokenizerstring
stemmerstring
stopwordsstring list, bare language name, or {languages, custom} set
memory'cold', 'cached', or 'pinned'

A bare language (stopwords = 'english') plans to the languages set. Unknown languages fail at plan; unknown set keys fail at parse.

prefix = true enables keyword prefix matching for WHERE field MATCH PREFIX (Qdrant 1.19+). DROP INDEX ON COLLECTION research FOR field removes an index.

There is no SHOW INDEXES. The supported forms are:

StatementReturns
SHOW COLLECTIONS;All collection names
SHOW COLLECTION name;A single collection's configuration
SHOW SHARD KEYS ON COLLECTION name;The custom shard keys of a collection
SHOW QUOTAS;Cluster-wide resource quota config and utilization (REST only)

SHOW QUOTAS and SET QUOTA (...) map to Qdrant's GET|PUT /quotas REST API. They are not available over gRPC (QQL-GRPC-QUOTA) or the edge backend (QQL-EDGE-UNSUPPORTED-QUOTA).

SET QUOTA is a full replace: PUT /quotas replaces the whole configuration. Omitted keys (including an explicit key = null) are unset in the replacement body — they do not merge with previous limits. Optional WAIT true|false waits for consensus after the update.

QQLInspect and replace cluster quotasTry in playground
SHOW QUOTAS;
SET QUOTA (enabled = true, max_resident_memory_percent = 80, max_disk_usage_percent = 90, release_margin_percent = 5) WAIT true;
SET QUOTA (enabled = false);
SET QUOTA (max_disk_usage_percent = null);

Invalid quota keys or out-of-range percentages fail planning with QQL-PLAN-QUOTA.

Shard-key DDL creates and manages routing partitions. It is separate from the tenant predicate your service must enforce.

QQLManage a custom shard keyTry in playground
CREATE SHARD KEY 'acme' ON COLLECTION research WITH (shards_number = 2);
CREATE SHARD KEY 'acme' ON COLLECTION research WITH (shards_number = 2, placement = [1, 2], initial_state = 'Active');
SHOW SHARD KEYS ON COLLECTION research;
DROP SHARD KEY 'acme' ON COLLECTION research;

placement is a peer-id list. initial_state is a replica-state string.

Next: Data operations and Multitenancy.