Problem/Motivation

We are running a quite big multi domain drupal site (all separate databases but running on the same database server) and found that in some cases we had lots of translation strings which needed to be updated within deployment of new versions.

Updating these would often trigger an update to the field 'version' in the table 'locales_location', which would end up being comparably slow. The reason we found was that the WHERE clause would contain a search by the field 'name', and that one is not indexed.

UPDATE locales_location SET version='8.8.8'
WHERE (sid = '5760') AND (type = 'path') AND (name = '/our/custom/path');

We created a composite index for the contained fields and could see that our database load dropped by ~50% (!) immediately after that.

CREATE INDEX sid_type_name on locales_location (sid,type,name);

Point is that we actually do not want to do anything custom to Drupal's Core, respectively the core database structure if we can avoid it, and there might be reasons why there's no index on this field. Clearly creating an index could slow down operations like INSERT a bit. But this table seems to see far more SELECTs or UPDATEs where 'name' is involved.

So what I'm hoping to achieve here is either confirmation this should be considered an improvement and go into Drupal Core, or getting an answer explaining why this index is a bad idea.

Thank you in advance!

Proposed resolution

Index 'name' field in locales_location table

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Issue fork drupal-3156439

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

bonsaipuppy created an issue. See original summary.

matsbla’s picture

Issue tags: +Performance
lendude’s picture

Version: 8.8.x-dev » 9.2.x-dev
Component: language system » locale.module
Category: Bug report » Feature request
Issue tags: +Bug Smash Initiative

Sounds reasonable. Moving to the right version and since there is indeed a trade off here, I'm going to mark this as a feature and not a bug.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

mkalkbrenner’s picture

Category: Feature request » Bug report
Priority: Normal » Major

We just ran into a similar issue when upgrading from Drupal 10.2.x to Drupal 10.3.0. The DB update took very long, 16min 23sec.
So I monitored the database queries during the update and found thousands of similar queries that could not use an index and lead to full table scans:

SELECT "s".*, "t"."language" AS "language", "t"."translation" AS "translation", "t"."customized" AS "customized"
FROM
"locales_source" "s"
LEFT OUTER JOIN "locales_target" "t" ON t.lid = s.lid AND t.language = 'fr'
WHERE "s"."lid" IN (SELECT "l"."sid" AS "sid"
FROM
"locales_location" "l"
WHERE ("l"."type" IN ('configuration')) AND ("l"."name" IN ('core.entity_form_mode.simplenews_subscriber.page')))
+------+--------------+-------------+--------+---------------+--------------+---------+----------------+--------+-------------+
| id   | select_type  | table       | type   | possible_keys | key          | key_len | ref            | rows   | Extra       |
+------+--------------+-------------+--------+---------------+--------------+---------+----------------+--------+-------------+
|    1 | PRIMARY      | s           | ALL    | PRIMARY       | NULL         | NULL    | NULL           | 114137 |             |
|    1 | PRIMARY      | t           | eq_ref | PRIMARY,lid   | PRIMARY      | 18      | const,db.s.lid | 1      | Using where |
|    1 | PRIMARY      | <subquery2> | eq_ref | distinct_key  | distinct_key | 4       | func           | 1      |             |
|    2 | MATERIALIZED | l           | ALL    | string_type   | NULL         | NULL    | NULL           | 85039  | Using where |
+------+--------------+-------------+--------+---------------+--------------+---------+----------------+--------+-------------+

After adding an appropriate index with

ALTER TABLE locales_location ADD INDEX (type, name);

these queries run much faster and the entire update only took only 36sec! The explain of such a single query with that index is

+------+--------------+-------------+--------+------------------+---------+---------+----------------+------+-----------------------+
| id   | select_type  | table       | type   | possible_keys    | key     | key_len | ref            | rows | Extra                 |
+------+--------------+-------------+--------+------------------+---------+---------+----------------+------+-----------------------+
|    1 | PRIMARY      | <subquery2> | ALL    | distinct_key     | NULL    | NULL    | NULL           | 1    |                       |
|    1 | PRIMARY      | s           | eq_ref | PRIMARY          | PRIMARY | 4       | db.l.sid       | 1    |                       |
|    1 | PRIMARY      | t           | eq_ref | PRIMARY,lid      | PRIMARY | 18      | const,db.l.sid | 1    | Using where           |
|    2 | MATERIALIZED | l           | ref    | string_type,type | type    | 1074    | const,const    | 1    | Using index condition |
+------+--------------+-------------+--------+------------------+---------+---------+----------------+------+-----------------------+

I think that this is a major issue. An update that takes more that 16min looks like the update process is frozen.

If we combine this with the initially reported issue, the index should be

ALTER TABLE locales_location ADD INDEX (type, name, sid);
alexpott’s picture

Status: Active » Needs work

@mkalkbrenner thanks for the sleuthing.

There's is already an index on

    'indexes' => [
      'string_type' => ['sid', 'type'],
    ],

So I think - looking at the queries on the issue and in the code that we only need to add an index on type and name. The query that requires this index is in \Drupal\locale\StringDatabaseStorage::dbStringSelect(). The other queries in the code all use lid (the primary key) or have sid and type defined which is already indexed.

alexpott’s picture

Status: Needs work » Needs review

This issue is going to need us to resolve #3108658: Handling update path divergence between 11.x and 10.x... as ideally we'd be able to backport this to 10.x

catch’s picture

We could avoid blocking this on #3108658: Handling update path divergence between 11.x and 10.x if we backport it to 10.3, given it's in locale module so should benefit everyone with locale module installed, and won't run on sites without it installed, that might be OK but would need a second opinion.

Alternatively we might be OK if we have it in 10.4, 11.0 and 11.1 (and not 10.3) - but only if we don't backport any other database updates to locale module in 10.3 (very unlikely).

alexpott’s picture

I think given it is an index addition planning to backport everywhere and get it in 11.0.x before 11.0.0 makes sense. Will change the update number to reflect this.

alexpott’s picture

I've added an MR for 10.x and set the update number to 10101 which is the next available number. This could now be committed to 10.3.x and up as long as we get this done before 11.0.0....

longwave’s picture

FWIW the impact here is low and to ease the transition between Drupal 10 and 11 I agree that we should backport this to 11.0.

I would suggest setting the update number to 10300 if this is going to land in 10.3 though as that follows the convention we have used so far.

alexpott’s picture

Changed the update number to @longwave's recommendation.

catch’s picture

Status: Needs review » Needs work

One comment on the MR.

catch credited xjm.

catch’s picture

Two more comments on the MR - one from me, one via @xjm in slack. Other than that looks good though and I think we should backport to 10.3

quietone’s picture

Title: DB table locales_location slow selects/updates due to missing index on field 'name' » Add an index on locales_location on type and name
Issue summary: View changes
mkalkbrenner’s picture

I tested https://git.drupalcode.org/issue/drupal-3156439/-/tree/3156439-db-table-... and updated from 10.2 to 10.3 again. I can confirm that it increased the speed of the update as expected, 30 seconds instead of more than 16 minutes!

alexpott’s picture

Status: Needs work » Needs review

I've fixed two of the MR comments. I'm not convinced about the defensive coding for the update. I don't think we should support custom schema variations on module provided schema. And it erroring is good because in I think it requires human interaction to know what to do... say the index is called type_name and is an index on type, name and sid for example. Or it is sid, type, name as per the example original request.

catch’s picture

Status: Needs review » Reviewed & tested by the community

This looks great now, RTBC for me.

  • longwave committed dd402f2f on 10.3.x
    Issue #3156439 by alexpott, catch, bonsaipuppy, mkalkbrenner, longwave,...

  • longwave committed 5f2858c5 on 10.4.x
    Issue #3156439 by alexpott, catch, bonsaipuppy, mkalkbrenner, longwave,...

  • longwave committed bb09a543 on 11.0.x
    Issue #3156439 by alexpott, catch, bonsaipuppy, mkalkbrenner, longwave,...

  • longwave committed e81e6f86 on 11.x
    Issue #3156439 by alexpott, catch, bonsaipuppy, mkalkbrenner, longwave,...
longwave’s picture

Version: 11.x-dev » 10.3.x-dev
Status: Reviewed & tested by the community » Fixed
Issue tags: +10.3.1 release notes

Thanks, I think this satisfies all comments on the MR now.

Committed and pushed e81e6f869d to 11.x and bb09a54352 to 11.0.x. Thanks!

Committed and pushed 5f2858c540 to 10.4.x and dd402f2fec to 10.3.x. Thanks!

Tagging for 10.3.1 release notes as we don't usually add update hooks to patch releases.

quietone’s picture

Status: Fixed » Needs work

alexpott’s picture

Status: Needs work » Needs review

Created a small MR to get the test to pass on Postgres... by just skipping the index inspection shenanigans there.

alexpott changed the visibility of the branch 3156439-db-table-localeslocation-10.x to hidden.

alexpott changed the visibility of the branch 3156439-db-table-localeslocation to hidden.

alexpott’s picture

Status: Needs review » Fixed

alexpott changed the visibility of the branch 3156439-postgres-followup to hidden.

Status: Fixed » Closed (fixed)

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

xjm’s picture

Amending attribution.