From dd0c75189f0615b3cab18ad2d6733200ff0ebfc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Paris?= Date: Fri, 11 Sep 2020 23:48:32 +0200 Subject: [PATCH] Add explanation about implicit indexes --- docs/en/explanation/implicit-indexes.rst | 62 ++++++++++++++++++++++++ docs/en/sidebar.rst | 2 + lib/Doctrine/DBAL/Schema/Table.php | 12 +++-- 3 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 docs/en/explanation/implicit-indexes.rst diff --git a/docs/en/explanation/implicit-indexes.rst b/docs/en/explanation/implicit-indexes.rst new file mode 100644 index 00000000000..f68edbe3ffb --- /dev/null +++ b/docs/en/explanation/implicit-indexes.rst @@ -0,0 +1,62 @@ +Implicit indexes +================ + +Ever noticed the DBAL creating indexes you did not remember asking for, +with names such as ``IDX_885DBAFAA76ED395``? In this document, we will +distinguish three types of indexes: + +user-defined indexes + indexes you did ask for + +DBAL-defined indexes + indexes you did not ask for, created on your behalf by the DBAL + +RDBMS-defined indexes + indexes you did not ask for, created on your behalf by the RDBMS + +RDBMS-defined indexes can be created by some database platforms when you +create a foreign key: they will create an index on the referencing +table, using the referencing columns. + +The rationale behind this is that these indexes improve performance, for +instance for checking that a delete operation can be performed on a +referenced table without violating the constraint in the referencing +table. + +Here are some database platforms that are known to create indexes when +creating a foreign key: + +- `MySQL `_ +- `MariaDB `_ + +These platforms can drop an existing implicit index once it is fulfilled +by a newly created user-defined index. + +Some other will not do so, on grounds that such indexes are not always +needed, and can be created in many different ways. They instead leave +that responsibility to the user: + +- `PostgreSQL `_ +- `SQLite `_ +- `SQL Server `_ + +Regardless of the behavior of the platform, the DBAL will create an +index for you and will automatically pick an index name that obeys +string length constraints of the platform you are using. That way, +differences between platforms are reduced because you always end up with +an index. + +This is a detail, but these indexes will be prefixed with ``IDX_``, and +typically look like this: + +.. code-block:: sql + + CREATE INDEX IDX_885DBAFAA76ED395 ON posts (user_id) + +In the case of MariaDB and MySQL, the creation of that DBAL-defined +index will result in the RDBMS-defined index being dropped. + +You can still explicitly create such indexes yourself, and the DBAL will +notice when your index fulfills the indexing and constraint needs of the +implicit index it would create, and will refrain from doing so, much +like some platforms drop indexes that are redundant as explained above. diff --git a/docs/en/sidebar.rst b/docs/en/sidebar.rst index 0935c8dc179..4ada9f1caf1 100644 --- a/docs/en/sidebar.rst +++ b/docs/en/sidebar.rst @@ -20,3 +20,5 @@ reference/caching reference/known-vendor-issues reference/upgrading + + explanation/implicit-indexes diff --git a/lib/Doctrine/DBAL/Schema/Table.php b/lib/Doctrine/DBAL/Schema/Table.php index 909b349107b..bd0462151a4 100644 --- a/lib/Doctrine/DBAL/Schema/Table.php +++ b/lib/Doctrine/DBAL/Schema/Table.php @@ -554,11 +554,13 @@ protected function _addForeignKeyConstraint(ForeignKeyConstraint $constraint) $this->_fkConstraints[$name] = $constraint; - // Add an explicit index on the foreign key columns. - // If there is already an index that fulfils this requirements drop the request. - // In the case of __construct calling this method during hydration from schema-details - // all the explicitly added indexes lead to duplicates. This creates computation overhead in this case, - // however no duplicate indexes are ever added (based on columns). + /* Add an implicit index (defined by the DBAL) on the foreign key + columns. If there is already a user-defined index that fulfills these + requirements drop the request. In the case of __construct() calling + this method during hydration from schema-details, all the explicitly + added indexes lead to duplicates. This creates computation overhead in + this case, however no duplicate indexes are ever added (based on + columns). */ $indexName = $this->_generateIdentifierName( array_merge([$this->getName()], $constraint->getColumns()), 'idx',