diff --git a/src/explanation/referential-integrity.md b/src/explanation/referential-integrity.md index 273e6216..870e4e53 100644 --- a/src/explanation/referential-integrity.md +++ b/src/explanation/referential-integrity.md @@ -105,13 +105,16 @@ quietly rewritten. ### 5. Indexing the foreign-key columns -On MySQL/InnoDB the engine automatically creates a secondary index on the -child's foreign-key columns as part of enforcing the constraint — you never +The child's foreign-key columns are always indexed, on both backends — you never declare it. Such an index accelerates the delete check (finding a parent's children), the join (matching child keys to parent keys), and the insert check -(confirming the parent exists). PostgreSQL does *not* index foreign-key columns -automatically; when the delete or join cost on a large child table matters, -declare an explicit `index(...)` on those columns. +(confirming the parent exists). On MySQL/InnoDB the engine creates the index +implicitly as part of enforcing the constraint. PostgreSQL does *not* index +foreign-key columns automatically, so DataJoint emits the index itself — skipping +it only when those columns are already covered (a left-prefix of the primary key +or of a declared index). Either way, the mental model holds: the database indexes +foreign-key columns. See the +[table-declaration spec](../reference/specs/table-declaration.md#26-foreign-key-indexes). ## The dual role: integrity and workflow diff --git a/src/reference/specs/database-backends.md b/src/reference/specs/database-backends.md index d25c3225..1b4dcf06 100644 --- a/src/reference/specs/database-backends.md +++ b/src/reference/specs/database-backends.md @@ -90,6 +90,11 @@ The following features work identically across all backends: | JSON operators | `->`, `->>` | `->`, `->>` | | BLOB storage | `LONGBLOB` | `BYTEA` | | Boolean type | `TINYINT(1)` | `BOOLEAN` | +| Foreign-key column index | Implicit (InnoDB) | Emitted by DataJoint (coverage-aware) | + +DataJoint guarantees foreign-key columns are indexed on both backends; the +difference above is only *who* creates the index. See +[Foreign-Key Indexes](table-declaration.md#26-foreign-key-indexes). ### String Quoting diff --git a/src/reference/specs/table-declaration.md b/src/reference/specs/table-declaration.md index ca68bfb0..6e62a516 100644 --- a/src/reference/specs/table-declaration.md +++ b/src/reference/specs/table-declaration.md @@ -130,6 +130,26 @@ Internally, singleton tables use a hidden `_singleton` attribute of type `bool` - Excluded from `fetch()` results - Excluded from join matching +### 2.6 Foreign-Key Indexes + +DataJoint guarantees that a foreign key's referencing (child) columns are +indexed, so foreign-key joins, cascade deletes, and the parent-existence check +are index-supported on every backend. + +- On **MySQL/InnoDB** the index is created implicitly as part of enforcing the + constraint; DataJoint declares nothing. +- On **PostgreSQL**, which does not index foreign-key columns automatically, + DataJoint emits the index itself. + +The emitted index is **coverage-aware**: it is skipped when the foreign-key +columns are already a left-prefix of an existing index — the table's primary key, +a declared `index(...)`/`unique index(...)`, or a wider foreign-key index — since +that index already serves the lookups. So a *leading* primary foreign key adds no +index, while a *secondary* foreign key or one in a *non-leading* position of a +composite primary key gets its own. A `unique` foreign key always carries its +`UNIQUE INDEX` on both backends. (Index lifecycle on foreign-key drop / `alter()` +is out of scope of declaration; see the schema-changes specification.) + --- ## 3. Attribute Definition