Backfill award_emoji sharding key
What does this MR do and why?
Backfill award_emoji sharding key.
Setting namespace_id or organization_id depending on record type. Organization_id is only set for records related to personal snippets (might be related through the notes table)
We never update records on this table, so it's safe to add the num_nonnulls constraint. Evidence of no updates in PG stats (internal only)
awardable_type list
awardable types in .com
select distinct(awardable_type) from award_emoji;
awardable_type
----------------
Epic
Issue
MergeRequest
Note
Snippet
(5 rows)Irreversible migrations (DELETE) details
Recover data
The migration will insert every deleted records into the award_emoji_archived table. If needed, those records can be moved back into the award_emoji table.
Impact on user experience if records go missing
award_emoji holds every emoji that has been awarded by any user to an Issue, MR, Note, Epic or Snippet. If records go missing, award emoji won't be displayed in the associated records
Query plans
Update Issue related records
https://console.postgres.ai/gitlab/gitlab-production-main/sessions/45408/commands/139189
WITH relation AS MATERIALIZED (
SELECT
"award_emoji".*
FROM
"award_emoji"
WHERE
"award_emoji"."id" BETWEEN 1
AND 10487
AND "award_emoji"."id" >= 1
AND "award_emoji"."id" < 113
LIMIT
100
), filtered_relation AS MATERIALIZED (
SELECT
*
from
relation
WHERE
"awardable_type" = 'Issue'
LIMIT
100
)
UPDATE
"award_emoji"
SET
"namespace_id" = "issues"."namespace_id"
FROM
filtered_relation
INNER JOIN "issues" ON "issues"."id" = filtered_relation."awardable_id"
WHERE
"award_emoji"."id" = filtered_relation."id"MergeRequest related records
https://console.postgres.ai/gitlab/gitlab-production-main/sessions/45408/commands/139191
WITH relation AS MATERIALIZED (
SELECT
"award_emoji".*
FROM
"award_emoji"
WHERE
"award_emoji"."id" BETWEEN 1
AND 10487
AND "award_emoji"."id" >= 1
AND "award_emoji"."id" < 113
LIMIT
100
), filtered_relation AS MATERIALIZED (
SELECT
*
from
relation
WHERE
"awardable_type" = 'MergeRequest'
LIMIT
100
)
UPDATE
"award_emoji"
SET
"namespace_id" = "projects"."project_namespace_id"
FROM
filtered_relation
INNER JOIN "merge_requests" ON "merge_requests"."id" = filtered_relation."awardable_id"
INNER JOIN "projects" ON "projects"."id" = "merge_requests"."target_project_id"
WHERE
"award_emoji"."id" = filtered_relation."id"Epic related records
https://console.postgres.ai/gitlab/gitlab-production-main/sessions/45408/commands/139192
WITH relation AS MATERIALIZED (
SELECT
"award_emoji".*
FROM
"award_emoji"
WHERE
"award_emoji"."id" BETWEEN 991887
AND 1003180
AND "award_emoji"."id" >= 991887
AND "award_emoji"."id" < 991997
LIMIT
100
), filtered_relation AS MATERIALIZED (
SELECT
*
from
relation
WHERE
"awardable_type" = 'Epic'
LIMIT
100
)
UPDATE
"award_emoji"
SET
"namespace_id" = "epics"."group_id"
FROM
filtered_relation
INNER JOIN "epics" ON "epics"."id" = filtered_relation."awardable_id"
WHERE
"award_emoji"."id" = filtered_relation."id"Snippet related records
https://console.postgres.ai/gitlab/gitlab-production-main/sessions/45408/commands/139193
WITH relation AS MATERIALIZED (
SELECT
"award_emoji".*
FROM
"award_emoji"
WHERE
"award_emoji"."id" BETWEEN 5044965
AND 5062565
AND "award_emoji"."id" >= 5044965
AND "award_emoji"."id" < 5045069
LIMIT
100
), filtered_relation AS MATERIALIZED (
SELECT
*
from
relation
WHERE
"awardable_type" = 'Snippet'
LIMIT
100
)
UPDATE
"award_emoji"
SET
"namespace_id" = "projects"."project_namespace_id",
"organization_id" = "snippets"."organization_id"
FROM
filtered_relation
INNER JOIN "snippets" ON "snippets"."id" = filtered_relation."awardable_id"
LEFT JOIN "projects" ON "projects"."id" = "snippets"."project_id"
WHERE
"award_emoji"."id" = filtered_relation."id"~~Note related records~~ (legacy query without case)
https://console.postgres.ai/gitlab/gitlab-production-main/sessions/45408/commands/139194
WITH relation AS MATERIALIZED (
SELECT
"award_emoji".*
FROM
"award_emoji"
WHERE
"award_emoji"."id" BETWEEN 5044965
AND 5062565
AND "award_emoji"."id" >= 5044965
AND "award_emoji"."id" < 5045069
LIMIT
100
), filtered_relation AS MATERIALIZED (
SELECT
*
from
relation
WHERE
"awardable_type" = 'Note'
LIMIT
100
), relation_with_sk AS MATERIALIZED (
SELECT
"filtered_relation"."id",
"notes"."organization_id",
COALESCE(
"projects"."project_namespace_id",
"notes"."namespace_id"
) AS namespace_id
FROM
"filtered_relation"
INNER JOIN "notes" ON "notes"."id" = "filtered_relation"."awardable_id"
LEFT JOIN "projects" ON "projects"."id" = "notes"."project_id"
LIMIT
100
)
UPDATE
"award_emoji"
SET
"namespace_id" = "relation_with_sk"."namespace_id",
"organization_id" = "relation_with_sk"."organization_id"
FROM
"relation_with_sk"
WHERE
"award_emoji"."id" = "relation_with_sk"."id"Update notes related records with case statement
https://console.postgres.ai/gitlab/gitlab-production-main/sessions/45612/commands/139792
WITH relation AS MATERIALIZED (
SELECT
"award_emoji".*
FROM
"award_emoji"
WHERE
"award_emoji"."id" BETWEEN 5044965
AND 5062565
AND "award_emoji"."id" >= 5044965
AND "award_emoji"."id" < 5045069
LIMIT
100
), filtered_relation AS MATERIALIZED (
SELECT
*
from
relation
WHERE
"awardable_type" = 'Note'
LIMIT
100
), relation_with_sk AS MATERIALIZED (
SELECT
"filtered_relation"."id",
COALESCE(
"projects"."project_namespace_id",
"notes"."namespace_id"
) AS namespace_id,
CASE WHEN num_nonnulls(
"notes"."project_id", "notes"."namespace_id"
) >= 1 THEN NULL ELSE "notes"."organization_id" END AS organization_id
FROM
"filtered_relation"
INNER JOIN "notes" ON "notes"."id" = "filtered_relation"."awardable_id"
LEFT JOIN "projects" ON "projects"."id" = "notes"."project_id"
LIMIT
100
)
UPDATE
"award_emoji"
SET
"namespace_id" = "relation_with_sk"."namespace_id",
"organization_id" = "relation_with_sk"."organization_id"
FROM
"relation_with_sk"
WHERE
"award_emoji"."id" = "relation_with_sk"."id"DELETE and archive award_emoji without sharding key
https://console.postgres.ai/gitlab/gitlab-production-main/sessions/45408/commands/139199
In the plans above I backfilled 40 note related records in the same batch, that's why in here we delete and archive 60 records
WITH relation AS MATERIALIZED (
SELECT
"award_emoji".*
FROM
"award_emoji"
WHERE
"award_emoji"."id" BETWEEN 5044965
AND 5062565
AND "award_emoji"."id" >= 5044965
AND "award_emoji"."id" < 5045069
LIMIT
100
), filtered_relation AS MATERIALIZED (
SELECT
*
from
relation
WHERE
"namespace_id" IS NULL
AND "organization_id" IS NULL
LIMIT
100
), deleted_emoji AS MATERIALIZED (
DELETE FROM
"award_emoji"
WHERE
"id" IN (
SELECT
"id"
FROM
filtered_relation
) RETURNING id,
name,
user_id,
awardable_id,
awardable_type,
created_at,
updated_at,
namespace_id,
organization_id
) INSERT INTO award_emoji_archived (
id, name, user_id, awardable_id, awardable_type,
created_at, updated_at, namespace_id,
organization_id
)
SELECT
id,
name,
user_id,
awardable_id,
awardable_type,
created_at,
updated_at,
namespace_id,
organization_id
FROM
deleted_emojiMR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.
Related to #514604 (closed)