1

Lately in one of our prod database the "key_value" table became 2.4GB large. When I took a closer look I could see that there is around 200 000 records in it, and 90% of them are entity_autocomplete collection. Then I searched the entity reference module where does it operate with the keyValue service and I found the following:

// \Drupal\Core\Entity\Element\EntityAutocomplete:129
   $selection_settings = isset($element['#selection_settings']) ? $element['#selection_settings'] : [];
    $data = serialize($selection_settings) . $element['#target_type'] . $element['#selection_handler'];
    $selection_settings_key = Crypt::hmacBase64($data, Settings::getHashSalt());

    $key_value_storage = \Drupal::keyValue('entity_autocomplete');
    if (!$key_value_storage->has($selection_settings_key)) {
      $key_value_storage->set($selection_settings_key, $selection_settings);
    }

The $selection_settings may contain the host entity as well (it's because of the self reference feature). This means based on the code: whenever you have a new entity or the entity updated your $selection_settings_key will always be different. Also it's added to the key-value table without expiration date which will end up as a permanent out of date record (after the entity changed / field config anyhow) in your key-value table. Also because it's serializing the whole entity the record itself can be quite big (talking about 10-12 KB).

Is this a bug or am I missing something?

0

Known bug: https://www.drupal.org/project/drupal/issues/2826826#comment-12376276

As mentioned in IRC, the problem with adding even just the entity id/UUID to those options is that we create entity * entity reference key value entries.

The key is based on the hash, so an ID/UUID in there results in a different hash for every entity. At the very least, we would need to switch to an expirable key value store, so we can clean them up but it is still a non-trivial overhead that is being added.

https://www.drupal.org/project/drupal/issues/2826826#comment-12644652

Seems to fix it for me:

    // Don't serialise the entity, it will be added explicitly afterwards.
if (isset($selection_settings['entity']) && ($selection_settings['entity'] instanceof EntityInterface)) {
  $element['#autocomplete_query_parameters']['host_entity_type'] = $selection_settings['entity']->getEntityTypeId();
  $element['#autocomplete_query_parameters']['host_entity_id'] = $selection_settings['entity']->id();
  unset($selection_settings['entity']);
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.