Problem/Motivation

We currently have some issues with the {key_value_expire} table. Basically, the main problem is that deleting rows is very slow because the records are so large. That's probably additionally slowed down in our case because we have a database cluster.

We're on an older core version, so the problem is bigger for us, but I think it still wouldn't hurt to improve this.

Proposed resolution

@DamZ suggested to change the primary key to (expire, collection, name). The primary problem seems to be that InnoDB always needs to re-order the data for the primary key and needs to move huge amounts of data around. When he first part of the PK is the expire column, then that never has to change, we can just always append data.

I guess we'd add a unique key on collection, name (or name, collection, not sure what's more performant) then and remove the index on the expire column and the all index then.

Remaining tasks

User interface changes

API changes

Data model changes

Indexes need to be removed/added. Especially for the PK, that can be a very slow operation if there's a lot of data already.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Fabianx’s picture

Priority: Normal » Major
Issue tags: +D8 upgrade path

Setting to major, if expire is not in the PK, that is a problem for the query parser IIRC.

To clarify:

- Do we have any key on 'expire' right now?

Overall: +1 to the approach and +1 to getting it in before supporting upgrade path as that could get hairy on production.

Best to delete the table and have key-value-expire recreate it automatically (except its installed by system module still ... so that won't work ... ).

catch’s picture

MariaDB [d8]> SHOW INDEXES FROM key_value_expire;
+------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table            | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| key_value_expire |          0 | PRIMARY  |            1 | collection  | A         |           5 |     NULL | NULL   |      | BTREE      |         |               |
| key_value_expire |          0 | PRIMARY  |            2 | name        | A         |           5 |     NULL | NULL   |      | BTREE      |         |               |
| key_value_expire |          1 | all      |            1 | name        | A         |           5 |     NULL | NULL   |      | BTREE      |         |               |
| key_value_expire |          1 | all      |            2 | collection  | A         |           5 |     NULL | NULL   |      | BTREE      |         |               |
| key_value_expire |          1 | all      |            3 | expire      | A         |           5 |     NULL | NULL   |      | BTREE      |         |               |
| key_value_expire |          1 | expire   |            1 | expire      | A         |           5 |     NULL | NULL   |      | BTREE      |         |               |
+------------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
6 rows in set (0.00 sec)

@berdir, would you mind seeing what happens if you drop the 'all' key? We don't have any queries that need that as far as I can see.

catch’s picture

Best to delete the table and have key-value-expire recreate it automatically (except its installed by system module still ... so that won't work ... ).

So I'd be up for fixing that properly, but also the update could just delete and recreate manually for now.

Berdir’s picture

Yes, deleting that index seems to help a bit, don't have too reliable numbers as it's not very constant.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

cilefen’s picture

Issue tags: +neworleans2016, +Triaged for D8 major current state

I am triaging Major issues at New Orleans. Nothing has changed about this situation. This is a major performance issue at the database level. I've tagged it on the assumption that this would be a releaseable change. It seems that way based on the conversation.

xjm’s picture

Thanks @cilefen for helping triage majors at the sprint. Updating issue credit.

catch’s picture

Issue tags: +Triaged core major

Discussed this with @xjm, @alexpott, @webchick and @cottser and agreed this is definitely major due to the severe scalability issue.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

catch’s picture

This is still valid as far as I can see.

In #2510438-2: Remove 'all' index from {key_value_expire} - serves no purpose and negatively impacts performance I suggested dropping the 'all' key - this would just need system_schema() updating and a straightforward update hook to drop the index. IMO this could still be backported to 8.9.x

We could then open a follow-up to discuss changing the primary key altogether. #2664322: key_value table is only used by a core service but it depends on system install would simplify the update there since we could simply drop the existing table in the update. That kind of change I think we'd need to do only in a minor release, so 9.1.x only.

quietone’s picture

Issue tags: -bugsmash +Bug Smash Initiative
johnwebdev’s picture

Assigned: Unassigned » johnwebdev

Working on this :)

johnwebdev’s picture

Assigned: johnwebdev » Unassigned
Status: Active » Needs review
FileSize
1.93 KB
jungle’s picture

+++ b/core/modules/system/tests/src/Functional/Update/DropIndexAllOnKeyValueExpireTableUpdateTest.php
@@ -0,0 +1,35 @@
+    $this->databaseDumpFiles = [
+      __DIR__ . '/../../../fixtures/update/drupal-8.8.0.bare.standard.php.gz',

Could be dirname(__DIR__, 3) . '/fixtures/update/drupal-8.8.0.bare.standard.php.gz',

jungle’s picture

Sorry, the patch is empty, Thanks @johnwebdev for the ping!

catch’s picture

Title: {key_value_expire} should have expire in the primary key » Remove 'all' index from {key_value_expire} - serves no purpose and negatively impacts performance

Re-titling.

catch’s picture

Just on the original suggestion here as opposed to the current patch:

@DamZ suggested to change the primary key to (expire, collection, name).

If we did this, we'd have no database-level constraint preventing duplicates for collection, name - so assuming we want to keep that, we'd need to make a new unique index on collection, name. Not sure that would necessarily help with the deletion issue unless it's specifically the primary key causing the problem here.

Berdir’s picture

I created this issue a long time ago. Back then, form_state storage/cache was still written for every new form, which caused _massive_ amounts of data being written to that table, non-stop. So 99% of the records being written were large and had a pretty stable, steadily increasing expiration.

Back when Damien explained this to me he said that having the expire in there would allow MySQL to manager the primary key much more efficiently, as I understand it now, it has to reorganize it on delete.

That it hasn't been a severe issue anymore for a long time, so IMHO I'm fine with that smaller improvement and also happy to move this down to a normal issue, I don't think it is major anymore.

Status: Needs review » Needs work

The last submitted patch, 21: 2510438-21.patch, failed testing. View results

larowlan’s picture

Priority: Major » Normal

Based on #24

catch’s picture

Given #24 I don't think we need the follow-up here for the primary key change at all.

quietone’s picture

quietone’s picture

Version: 8.9.x-dev » 9.2.x-dev
daffie’s picture

+++ b/core/modules/system/system.install
@@ -1447,3 +1447,11 @@ function system_update_8901() {
+  $schema->dropIndex('key_value_expire', 'all');

Could we test first for the existence of the table. The function dropIndex() does not like it when you try to drop an index from a non-existing table.

quietone’s picture

daffie’s picture

Status: Needs review » Reviewed & tested by the community

The removed index is not used.
There update function added to the patch for existing sites.
There is testing added to the update function.
For me it is RTBC.

catch’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/system/tests/src/Functional/Update/DropIndexAllOnKeyValueExpireTableUpdateTest.php
@@ -0,0 +1,35 @@
+ *
+ * @group Update
+ * @see system_update_8902
+ */

This should be system_update_9201().

However, I'm not sure this needs to be a hook_update_N() since it's only dropping an index rather than changing the way data is scored in the schema. If we made it a post update, it would also help us avoid running into #3108658: [policy] Handling update path divergence between 11.x and 10.x.

ravi.shankar’s picture

Updated as per comment #33.

daffie’s picture

+++ b/core/modules/system/system.install
@@ -1447,3 +1447,13 @@ function system_update_8901() {
+function system_update_9201() {

This function should be changed to a hook_post_update_NAME() function as requested by @catch in comment #33.

ankithashetty’s picture

Status: Needs work » Needs review
FileSize
2.34 KB
1.11 KB

Updated patch in #34 addressing #35. Thanks!

quietone’s picture

Status: Needs review » Needs work

The link given by catch in #33 suggests changes that still need to be implemented here.

daffie’s picture

Status: Needs work » Reviewed & tested by the community

The update function has been changed to post update function and that was what @catch wanted in comment #33.
Therefore back to RTBC.

@quietone: If I am missing something, then please explain what.

quietone’s picture

@daffie, thanks for asking. I reread the issue referred to and learned that I misread the Proposed Resolution, substituting hook_post_update for hook_update which is wrong. So, yes, the changes requested in #33 are complete now.

catch’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/system/system.install
@@ -1447,3 +1447,13 @@ function system_update_8901() {
+ */
+function system_post_update_9201() {
+  $schema = \Drupal::database()->schema();

This should be moved to system.post_update.php and also named something like 'system_post_update_remove_key_value_expire_all_index()' - since there's no numbering of post updates.

longwave’s picture

Status: Needs work » Needs review
FileSize
2.48 KB
1.88 KB
johnwebdev’s picture

Status: Needs review » Reviewed & tested by the community

  • catch committed 1fb62cc on 9.2.x
    Issue #2510438 by quietone, jungle, ravi.shankar, ankithashetty,...
catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed 1fb62cc and pushed to 9.2.x. Thanks!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.