Ghost/ghost
Kevin Ansfield d5a9731845
Fixed email_recipients indexes to match query usage (#19918)
closes https://linear.app/tryghost/issue/ENG-791/migration-to-fix-email-recipients-indexes

Our indexes over single columns (`delivered_at`, `opened_at`, `failed_at`) were ineffective because the only time we query those is alongside `email_id` meaning we were frequently performing full table scans on very large tables during our email analytics jobs.

- added migration to add new indexes covering `email_id` and the respective columns
- added migration to drop the old indexes that weren't being used in any query plans

Local runtime with ~2M email_recipient rows:
- before: 1.7s
- after: 99ms

Explain output...

before:
```
+----+-------------+------------------+------------+-------+----------------------------------------------------------------------------------+----------------------------------------------+---------+-------+--------+----------+------------------------------------+
| id | select_type | table            | partitions | type  | possible_keys                                                                    | key                                          | key_len | ref   | rows   | filtered | Extra                              |
+----+-------------+------------------+------------+-------+----------------------------------------------------------------------------------+----------------------------------------------+---------+-------+--------+----------+------------------------------------+
|  1 | UPDATE      | emails           | NULL       | index | NULL                                                                             | PRIMARY                                      | 98      | NULL  |      1 |   100.00 | Using where                        |
|  4 | SUBQUERY    | email_recipients | NULL       | range | email_recipients_email_id_member_email_index,email_recipients_failed_at_index    | email_recipients_failed_at_index             | 6       | NULL  |   2343 |     7.76 | Using index condition; Using where |
|  3 | SUBQUERY    | email_recipients | NULL       | ref   | email_recipients_email_id_member_email_index,email_recipients_opened_at_index    | email_recipients_email_id_member_email_index | 98      | const | 159126 |    50.00 | Using where                        |
|  2 | SUBQUERY    | email_recipients | NULL       | ref   | email_recipients_email_id_member_email_index,email_recipients_delivered_at_index | email_recipients_email_id_member_email_index | 98      | const | 159126 |    50.00 | Using where                        |
+----+-------------+------------------+------------+-------+----------------------------------------------------------------------------------+----------------------------------------------+---------+-------+--------+----------+------------------------------------+
```

after:
```
+----+-------------+------------------+------------+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------+---------+------+--------+----------+--------------------------+
| id | select_type | table            | partitions | type  | possible_keys                                                                                                                                                                 | key                                          | key_len | ref  | rows   | filtered | Extra                    |
+----+-------------+------------------+------------+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------+---------+------+--------+----------+--------------------------+
|  1 | UPDATE      | emails           | NULL       | index | NULL                                                                                                                                                                          | PRIMARY                                      | 98      | NULL |      1 |   100.00 | Using where;             |
|  4 | SUBQUERY    | email_recipients | NULL       | range | email_recipients_email_id_member_email_index,email_recipients_email_id_delivered_at_index,email_recipients_email_id_opened_at_index,email_recipients_email_id_failed_at_index | email_recipients_email_id_failed_at_index    | 104     | NULL |     60 |   100.00 | Using where; Using index |
|  3 | SUBQUERY    | email_recipients | NULL       | range | email_recipients_email_id_member_email_index,email_recipients_email_id_delivered_at_index,email_recipients_email_id_opened_at_index,email_recipients_email_id_failed_at_index | email_recipients_email_id_opened_at_index    | 104     | NULL | 119496 |   100.00 | Using where; Using index |
|  2 | SUBQUERY    | email_recipients | NULL       | range | email_recipients_email_id_member_email_index,email_recipients_email_id_delivered_at_index,email_recipients_email_id_opened_at_index,email_recipients_email_id_failed_at_index | email_recipients_email_id_delivered_at_index | 104     | NULL | 146030 |   100.00 | Using where; Using index |
+----+-------------+------------------+------------+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------+---------+------+--------+----------+--------------------------+
```
2024-04-03 17:52:52 +01:00
..
adapter-cache-memory-ttl Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
adapter-cache-redis Implemented Refresh-Ahead caching for Redis 2024-01-18 20:16:36 +07:00
adapter-manager Aligned dependencies with resolution values 2023-10-13 08:37:36 +02:00
admin Removed confirmation modal when dismissing onboarding (#19979) 2024-04-03 16:46:38 +00:00
announcement-bar-settings Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
api-framework Cached api controller pipelines (#19880) 2024-03-19 00:29:41 +07:00
api-version-compatibility-service Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
audience-feedback Updated @tryghost/errors dependency 2024-03-11 17:33:51 +01:00
bookshelf-repository Removed usage of yg when using NQL (#19287) 2024-01-15 14:40:01 +00:00
bootstrap-socket Added queueing middleware to handle high request volume (#19887) 2024-03-21 09:25:07 -05:00
collections Added queueing middleware to handle high request volume (#19887) 2024-03-21 09:25:07 -05:00
constants Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
core Fixed email_recipients indexes to match query usage (#19918) 2024-04-03 17:52:52 +01:00
custom-theme-settings-service Updated @tryghost/errors dependency 2024-03-11 17:33:51 +01:00
data-generator Added support for clearing all data with data generator (#19901) 2024-03-25 14:44:28 +01:00
domain-events Added queueing middleware to handle high request volume (#19887) 2024-03-21 09:25:07 -05:00
donations Update dependency typescript to v5.4.3 2024-03-21 09:28:10 +01:00
dynamic-routing-events Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
email-addresses Update dependency typescript to v5.4.3 2024-03-21 09:28:10 +01:00
email-analytics-provider-mailgun Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
email-analytics-service Update TryGhost packages 2023-10-31 20:54:17 +01:00
email-content-generator Update dependency fs-extra to v11.2.0 2023-11-28 11:54:44 +01:00
email-events Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
email-service Removed Powered by Ghost clicks in publisher analytics (#19926) 2024-03-26 17:51:23 +01:00
email-suppression-list Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
express-dynamic-redirects Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
external-media-inliner Add Lexical support to the external-media-inliner (#19149) 2023-11-29 17:56:03 +00:00
extract-api-key Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
ghost Update nest monorepo to v10.3.7 2024-03-28 10:12:04 +01:00
html-to-plaintext Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
i18n Made changes in Turkish local for Comments, Ghost and Portal (#19919) 2024-03-27 08:21:16 -04:00
importer-handler-content-files Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
importer-revue 🐛 Fixed rare rendering issue of lists appearing as headings (#19511) 2024-01-22 09:43:05 +01:00
in-memory-repository Added tests to AdminX framework package (#19022) 2023-11-20 11:00:51 +00:00
job-manager Added queueing middleware to handle high request volume (#19887) 2024-03-21 09:25:07 -05:00
link-redirects Update Types packages 2023-11-08 12:13:12 +01:00
link-replacer 🐛 Fixed unexpected conversion of single-quoted attributes in HTML cards (#19727) 2024-03-06 09:11:49 +00:00
link-tracking Updated @tryghost/errors dependency 2024-03-11 17:33:51 +01:00
magic-link Updated @tryghost/errors dependency 2024-03-11 17:33:51 +01:00
mail-events Updated @tryghost/errors dependency 2024-03-11 17:33:51 +01:00
mailgun-client Added queueing middleware to handle high request volume (#19887) 2024-03-21 09:25:07 -05:00
member-attribution 🐛 Fixed unexpected conversion of single-quoted attributes in HTML cards (#19727) 2024-03-06 09:11:49 +00:00
member-events Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
members-api Update dependency express to v4.19.2 [SECURITY] 2024-03-27 11:18:44 +01:00
members-csv 🔒 Added escaping to member export CSV fields 2024-04-03 10:21:02 +02:00
members-events-service Added queueing middleware to handle high request volume (#19887) 2024-03-21 09:25:07 -05:00
members-importer Added queueing middleware to handle high request volume (#19887) 2024-03-21 09:25:07 -05:00
members-ssr Updated @tryghost/errors dependency 2024-03-11 17:33:51 +01:00
mentions-email-report Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
milestones Updated @tryghost/errors dependency 2024-03-11 17:33:51 +01:00
minifier Update dependency terser to v5.30.2 2024-04-02 13:08:00 +00:00
model-to-domain-event-interceptor Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
mw-api-version-mismatch Updated @tryghost/errors dependency 2024-03-11 17:33:51 +01:00
mw-cache-control Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
mw-error-handler Updated @tryghost/errors dependency 2024-03-11 17:33:51 +01:00
mw-session-from-token Update dependency express to v4.19.2 [SECURITY] 2024-03-27 11:18:44 +01:00
mw-update-user-last-seen Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
mw-version-match Updated @tryghost/errors dependency 2024-03-11 17:33:51 +01:00
mw-vhost Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
nql-filter-expansions Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
oembed-service Added queueing middleware to handle high request volume (#19887) 2024-03-21 09:25:07 -05:00
offers Updated @tryghost/errors dependency 2024-03-11 17:33:51 +01:00
package-json Updated @tryghost/errors dependency 2024-03-11 17:33:51 +01:00
payments Updated @tryghost/errors dependency 2024-03-11 17:33:51 +01:00
post-events Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
post-revisions Added tests to AdminX framework package (#19022) 2023-11-20 11:00:51 +00:00
posts-service Updated @tryghost/errors dependency 2024-03-11 17:33:51 +01:00
recommendations 🐛 Fixed adding recommendations with long excerpts (#19949) 2024-03-28 17:02:37 +01:00
referrers Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
security Update TryGhost packages 2023-10-31 20:54:17 +01:00
session-service Update dependency express to v4.19.2 [SECURITY] 2024-03-27 11:18:44 +01:00
settings-path-manager Updated @tryghost/errors dependency 2024-03-11 17:33:51 +01:00
slack-notifications Added ability to pass minThreshold for Milestone Slack notifications 2024-03-14 12:06:43 -04:00
staff-service Added email address alignment protections (#19094) 2023-11-23 10:25:30 +01:00
stats-service Update Types packages 2024-01-15 21:04:04 +01:00
stripe Added queueing middleware to handle high request volume (#19887) 2024-03-21 09:25:07 -05:00
tiers 🐛 Fixed Tiers API erroring when invalid filter passed (#19845) 2024-03-13 00:25:42 +07:00
update-check-service Added queueing middleware to handle high request volume (#19887) 2024-03-21 09:25:07 -05:00
verification-trigger Updated @tryghost/errors dependency 2024-03-11 17:33:51 +01:00
version-notifications-data-service Configured all unit tests to use dot reporter 2023-10-05 12:24:24 +02:00
webmentions Added queueing middleware to handle high request volume (#19887) 2024-03-21 09:25:07 -05:00
tsconfig.json Disabled TypeScript incremental building 2023-08-09 18:27:56 +02:00