Index en How to add a SQL index to existing entity tables <span class="field field--name-title field--type-string field--label-hidden">How to add a SQL index to existing entity tables</span> <span class="field field--name-uid field--type-entity-reference field--label-hidden"><span lang="" about="/user/1" typeof="schema:Person" property="schema:name" datatype="">LOBsTerr</span></span> <span class="field field--name-created field--type-created field--label-hidden">09/03/2019</span> <div class="field field--name-f-content field--type-entity-reference-revisions field--label-hidden field__items"> <div class="field__item"> <div class="paragraph paragraph--type--l-text paragraph--view-mode--default"> <div class="clearfix text-formatted field field--name-f-text field--type-text-long field--label-hidden field__item"><p>Drupal 8 provides a nice Entity API, which handles a lot of complicated mechanisms for us automatically. For example, the handling of tables for Content Entity. In some cases if we are fetching frequently entity tables and we need to improve the performance by providing additional indexes in database tables. There are different ways to do so. The first option you can think of to add directly using SQL query or Schema API. Obviously, it is not a the best way, because a lot of thing can go wrong here.</p> <p>Luckily Drupal 8 provides nice way to do it.</p> <p>First of all we need to define a Storage Schema class. Let's take as an example node module:</p> <pre> <code class="language-php">&lt;?php namespace Drupal\node; use Drupal\Core\Entity\ContentEntityTypeInterface; use Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema; use Drupal\Core\Field\FieldStorageDefinitionInterface; /** * Defines the node schema handler. */ class NodeStorageSchema extends SqlContentEntityStorageSchema { /** * {@inheritdoc} */ protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $reset = FALSE) { $schema = parent::getEntitySchema($entity_type, $reset); if ($data_table = $this-&gt;storage-&gt;getDataTable()) { $schema[$data_table]['indexes'] += [ 'node__frontpage' =&gt; ['promote', 'status', 'sticky', 'created'], 'node__title_type' =&gt; ['title', ['type', 4]], ]; } return $schema; } /** * {@inheritdoc} */ protected function getSharedTableFieldSchema(FieldStorageDefinitionInterface $storage_definition, $table_name, array $column_mapping) { $schema = parent::getSharedTableFieldSchema($storage_definition, $table_name, $column_mapping); $field_name = $storage_definition-&gt;getName(); if ($table_name == 'node_revision') { switch ($field_name) { case 'langcode': $this-&gt;addSharedTableFieldIndex($storage_definition, $schema, TRUE); break; case 'revision_uid': $this-&gt;addSharedTableFieldForeignKey($storage_definition, $schema, 'users', 'uid'); break; } } if ($table_name == 'node_field_data') { switch ($field_name) { case 'promote': case 'status': case 'sticky': case 'title': // Improves the performance of the indexes defined // in getEntitySchema(). $schema['fields'][$field_name]['not null'] = TRUE; break; case 'changed': case 'created': // @todo Revisit index definitions: // $this-&gt;addSharedTableFieldIndex($storage_definition, $schema, TRUE); break; } } return $schema; } } </code></pre> <p><br /> I will explain a little bit the code above before we continue. We have few options here</p> <p>1) Add composite index, which includes several fields like this:<br />  </p> <pre> <code class="language-php"> if ($data_table = $this-&gt;storage-&gt;getDataTable()) { $schema[$data_table]['indexes'] += [ 'node__frontpage' =&gt; ['promote', 'status', 'sticky', 'created'], 'node__title_type' =&gt; ['title', ['type', 4]], ]; }</code></pre> <p>2) Add an index for specific field:</p> <pre> <code class="language-php">case 'langcode': $this-&gt;addSharedTableFieldIndex($storage_definition, $schema, TRUE); break;</code></pre> <p>3) Add a foreign key</p> <pre> <code class="language-php">case 'revision_uid': $this-&gt;addSharedTableFieldForeignKey($storage_definition, $schema, 'users', 'uid'); break;</code></pre> <p>4) Add additional properties for the fields</p> <pre> <code class="language-php">case 'title': // Improves the performance of the indexes defined // in getEntitySchema(). $schema['fields'][$field_name]['not null'] = TRUE; break;</code></pre> <p> </p> <p>Now, when we have a class for Storage Schema, we need to add it to entity definition. Check Drupal\node\Entity\Node.php</p> <pre> <code class="language-php"> * handlers = { * "storage" = "Drupal\node\NodeStorage", * "storage_schema" = "Drupal\node\NodeStorageSchema", * "view_builder" = "Drupal\node\NodeViewBuilder",</code></pre> <p>No we to update our entity and set Storage Schema class for existing entity. We can do it using hook update</p> <pre> <code class="language-php">&lt;?php use Drupal\your_module\YourStorageSchema; /** * Add storage schema to entity type. */ function your_module_update_8017() { $manager = \Drupal::entityDefinitionUpdateManager(); // Get the current entity type definition, ensure the storage schema // class is set. $entity_type = $manager-&gt;getEntityType('enity_type') -&gt;setHandlerClass('storage_schema', YourStorageSchema::class); // Regenerate entity type indexes. $manager-&gt;updateEntityType($entity_type); }</code></pre> <p>Or if we have already had the Storage Schema class before, we can just update Entity type</p> <pre> <code class="language-php">&lt;?php use Drupal\your_module\YourStorageSchema; /** * Update entity type. */ function your_module_update_8017() { $manager = \Drupal::entityDefinitionUpdateManager(); $entity_type = $manager-&gt;getEntityType('enity_type'); // Regenerate entity type indexes. $manager-&gt;updateEntityType($entity_type); }</code></pre> <p> </p> </div> </div> </div> </div> <div class="field field--name-f-tags field--type-entity-reference field--label-hidden field__items"> <div class="field__item btn btn-secondary"><a href="/tags/drupal-9" hreflang="en">Drupal 9</a></div> <div class="field__item btn btn-secondary"><a href="/tags/entity" hreflang="en">Entity</a></div> <div class="field__item btn btn-secondary"><a href="/tags/entity-api" hreflang="en">Entity API</a></div> <div class="field__item btn btn-secondary"><a href="/tags/index" hreflang="en">Index</a></div> </div> <section class="field field--name-f-comments field--type-comment field--label-above comment-wrapper"> </section> Tue, 03 Sep 2019 08:18:28 +0000 LOBsTerr 9 at