Skip to content

CONCEPT

Vindex

A Vindex (short for Vitess Index) is Vitess's mapping from a row's column value to the keyspace_id that identifies the shard the row lives on. Vindexes are the primitive Vitess uses to route queries in a sharded database without scatter-gather.

"Vitess uses Vindexes (short for Vitess Index) to associate rows in a table with a designated address known as Keyspace ID. This allows Vitess to direct a row to its intended destination, typically a shard within the cluster."

Dual role: Primary and Secondary

Vindexes play two architectural roles:

  1. Primary Vindex — drives sharding. The Primary Vindex on a table is the column Vitess uses to decide which shard a row is stored on. Each table has exactly one Primary Vindex.

  2. Secondary Vindex — global index for non-sharding-key lookups. A Secondary Vindex on a non-sharding-key column lets Vitess route a query like SELECT … WHERE name = 'Alex' to a single shard instead of fanning out to all shards (scatter-gather).

Vitess's canonical example, verbatim from the article:

USER Table:
+-------+--------------+------+-----+
| Field | Type         | Null | Key |
+-------+--------------+------+-----+
| id    | bigint       | NO   | PRI |    ← Primary Vindex column
| name  | varchar(255) | YES  |     |
| phone | bigint       | YES  | UNI |    ← Secondary Vindex (unique)
| email | varchar(255) | YES  |     |
+-------+--------------+------+-----+

NAME_USER_VDX (Secondary Vindex, non-unique):
+-------------+--------------+------+-----+
| name        | varchar(255) | NO   | PRI |
| id          | bigint       | NO   | PRI |
| keyspace_id | binary(8)    | YES  |     |
+-------------+--------------+------+-----+

PHONE_USER_VDX (Secondary Vindex, unique):
+-------------+-----------+------+-----+
| phone       | bigint    | NO   | PRI |
| keyspace_id | binary(8) | YES  |     |
+-------------+-----------+------+-----+

Why Vindex tables are themselves sharded

The user data table is sharded by id (its Primary Vindex column). Vindex tables are also sharded — typically by the lookup column (name_user_vdx sharded by name, phone_user_vdx sharded by phone). This is what makes the index useful at scale: a query like WHERE phone = X hits only the one phone_user_vdx shard that owns that phone value.

But it also means one logical DML that writes a user row and its corresponding Vindex rows writes to shards that live on different columns — which is the cross-shard transaction problem that Consistent Lookup Vindex exists to solve.

Unique vs non-unique Secondary Vindexes

  • Unique: every column value maps to exactly one row (phone in the example). Inserts can hit duplicate-key errors and must be handled carefully — Vitess uses this as the trigger for orphan-row reclamation.
  • Non-unique: a column value may map to many rows (name in the example — multiple users can be named Emma). Inserts never collide on the lookup table.

Lookup Vindex vs functional Vindex

Vitess supports a taxonomy of Vindex types (docs). Functional Vindexes compute the keyspace_id from the column value directly (e.g. hash, numeric range). Lookup Vindexes materialise an explicit column → keyspace_id table in MySQL. This concept page focuses on Lookup Vindexes, which is what the 2026-04-21 Consistent Lookup Vindex post covers.

Seen in

  • — canonical wiki introduction of the Vindex primitive, dual Primary/Secondary role, sharded-lookup-table architecture, and the unique-vs-non-unique distinction.
  • first wiki source naming the concrete Primary Vindex function in a production VSchema: "xxhash": {"type": "xxhash"}. Savannah Longoria (PlanetScale, 2022-12-14) shows xxhash declared once in the keyspace-level vindexes block + referenced per-table in each sharded table's columnVindexes with the shard-key column name (shard_id or range_hash). Canonical pattern in the wiki for declaring a hash- sharding Primary Vindex on an existing shard-addressed column.
Last updated · 542 distilled / 1,571 read