From d9d800cfc4f8d49af632418494ae50f2bcff7880 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Wed, 10 Jan 2024 17:09:15 +0800 Subject: [PATCH 1/8] add index for sorting by saved_at --- packages/api/src/services/library_item.ts | 8 ++++++-- .../0153.do.library_item_user_id_saved_at_idx.sql | 6 ++++++ .../0153.undo.library_item_user_id_saved_at_idx.sql | 9 +++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100755 packages/db/migrations/0153.do.library_item_user_id_saved_at_idx.sql create mode 100755 packages/db/migrations/0153.undo.library_item_user_id_saved_at_idx.sql diff --git a/packages/api/src/services/library_item.ts b/packages/api/src/services/library_item.ts index 8478f33f3..339c7a26d 100644 --- a/packages/api/src/services/library_item.ts +++ b/packages/api/src/services/library_item.ts @@ -93,6 +93,7 @@ export enum SortOrder { export interface Sort { by: string order?: SortOrder + nulls?: 'NULLS FIRST' | 'NULLS LAST' } interface Select { @@ -332,8 +333,10 @@ export const buildQuery = ( const order = sortOrder === 'asc' ? SortOrder.ASCENDING : SortOrder.DESCENDING + const nulls = + order === SortOrder.ASCENDING ? 'NULLS FIRST' : 'NULLS LAST' - orders.push({ by: `library_item.${column}`, order }) + orders.push({ by: `library_item.${column}`, order, nulls }) return null } case 'has': @@ -613,12 +616,13 @@ export const searchLibraryItems = async ( orders.push({ by: 'library_item.saved_at', order: SortOrder.DESCENDING, + nulls: 'NULLS LAST', }) } // add order by orders.forEach((order) => { - queryBuilder.addOrderBy(order.by, order.order, 'NULLS LAST') + queryBuilder.addOrderBy(order.by, order.order, order.nulls) }) const libraryItems = await queryBuilder.skip(from).take(size).getMany() diff --git a/packages/db/migrations/0153.do.library_item_user_id_saved_at_idx.sql b/packages/db/migrations/0153.do.library_item_user_id_saved_at_idx.sql new file mode 100755 index 000000000..9161f6bcf --- /dev/null +++ b/packages/db/migrations/0153.do.library_item_user_id_saved_at_idx.sql @@ -0,0 +1,6 @@ +-- Type: DO +-- Name: library_item_user_id_saved_at_idx +-- Description: Add library_item_user_id_saved_at_idx index on library_item table for user_id and saved_at + +-- create index for sorting concurrently to avoid locking +CREATE INDEX CONCURRENTLY IF NOT EXISTS library_item_user_id_saved_at_idx ON omnivore.library_item (user_id, saved_at DESC NULLS LAST); diff --git a/packages/db/migrations/0153.undo.library_item_user_id_saved_at_idx.sql b/packages/db/migrations/0153.undo.library_item_user_id_saved_at_idx.sql new file mode 100755 index 000000000..7fc17a292 --- /dev/null +++ b/packages/db/migrations/0153.undo.library_item_user_id_saved_at_idx.sql @@ -0,0 +1,9 @@ +-- Type: UNDO +-- Name: library_item_user_id_saved_at_idx +-- Description: Add library_item_user_id_saved_at_idx index on library_item table for user_id and saved_at + +BEGIN; + +DROP INDEX IF EXISTS omnivore.library_item_user_id_saved_at_idx; + +COMMIT; From 7fba161d41669fc907354601481e5420431e5b12 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Wed, 10 Jan 2024 17:25:21 +0800 Subject: [PATCH 2/8] add index for sorting by updated_at --- .../0154.do.library_item_user_id_updated_at_idx.sql | 6 ++++++ .../0154.undo.library_item_user_id_updated_at_idx.sql | 9 +++++++++ 2 files changed, 15 insertions(+) create mode 100755 packages/db/migrations/0154.do.library_item_user_id_updated_at_idx.sql create mode 100755 packages/db/migrations/0154.undo.library_item_user_id_updated_at_idx.sql diff --git a/packages/db/migrations/0154.do.library_item_user_id_updated_at_idx.sql b/packages/db/migrations/0154.do.library_item_user_id_updated_at_idx.sql new file mode 100755 index 000000000..f7d62b541 --- /dev/null +++ b/packages/db/migrations/0154.do.library_item_user_id_updated_at_idx.sql @@ -0,0 +1,6 @@ +-- Type: DO +-- Name: library_item_user_id_updated_at_idx +-- Description: Add library_item_user_id_saved_at_idx index on library_item table for user_id and updated_at + +-- create index for sorting concurrently to avoid locking +CREATE INDEX CONCURRENTLY IF NOT EXISTS library_item_user_id_updated_at_idx ON omnivore.library_item (user_id, updated_at DESC NULLS LAST); diff --git a/packages/db/migrations/0154.undo.library_item_user_id_updated_at_idx.sql b/packages/db/migrations/0154.undo.library_item_user_id_updated_at_idx.sql new file mode 100755 index 000000000..eeb012f8a --- /dev/null +++ b/packages/db/migrations/0154.undo.library_item_user_id_updated_at_idx.sql @@ -0,0 +1,9 @@ +-- Type: UNDO +-- Name: library_item_user_id_updated_at_idx +-- Description: Add library_item_user_id_saved_at_idx index on library_item table for user_id and updated_at + +BEGIN; + +DROP INDEX IF EXISTS library_item_user_id_updated_at_idx; + +COMMIT; From d54af004d63aa6e40ccbbc11dcddb7e395d06527 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Wed, 10 Jan 2024 17:28:00 +0800 Subject: [PATCH 3/8] add index for sorting by published_at --- .../0155.do.library_item_user_id_published_at_idx.sql | 6 ++++++ .../0155.undo.library_item_user_id_published_at_idx.sql | 9 +++++++++ 2 files changed, 15 insertions(+) create mode 100755 packages/db/migrations/0155.do.library_item_user_id_published_at_idx.sql create mode 100755 packages/db/migrations/0155.undo.library_item_user_id_published_at_idx.sql diff --git a/packages/db/migrations/0155.do.library_item_user_id_published_at_idx.sql b/packages/db/migrations/0155.do.library_item_user_id_published_at_idx.sql new file mode 100755 index 000000000..ddc57ea11 --- /dev/null +++ b/packages/db/migrations/0155.do.library_item_user_id_published_at_idx.sql @@ -0,0 +1,6 @@ +-- Type: DO +-- Name: library_item_user_id_published_at_idx +-- Description: Add library_item_user_id_published_at_idx index on library_item table for user_id and published_at + +-- create index for sorting concurrently to avoid locking +CREATE INDEX CONCURRENTLY IF NOT EXISTS library_item_user_id_updated_at_idx ON omnivore.library_item (user_id, updated_at DESC NULLS LAST); diff --git a/packages/db/migrations/0155.undo.library_item_user_id_published_at_idx.sql b/packages/db/migrations/0155.undo.library_item_user_id_published_at_idx.sql new file mode 100755 index 000000000..388152849 --- /dev/null +++ b/packages/db/migrations/0155.undo.library_item_user_id_published_at_idx.sql @@ -0,0 +1,9 @@ +-- Type: UNDO +-- Name: library_item_user_id_published_at_idx +-- Description: Add library_item_user_id_published_at_idx index on library_item table for user_id and published_at + +BEGIN; + +DROP INDEX IF EXISTS library_item_user_id_published_at_idx; + +COMMIT; From 525b3fbacfbe13df5e54e3d3265736c1720f5d34 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Wed, 10 Jan 2024 17:32:23 +0800 Subject: [PATCH 4/8] add index for sorting by read_at --- .../0155.do.library_item_user_id_published_at_idx.sql | 2 +- .../0156.do.library_item_user_id_read_at_idx.sql | 6 ++++++ .../0156.undo.library_item_user_id_read_at_idx.sql | 9 +++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100755 packages/db/migrations/0156.do.library_item_user_id_read_at_idx.sql create mode 100755 packages/db/migrations/0156.undo.library_item_user_id_read_at_idx.sql diff --git a/packages/db/migrations/0155.do.library_item_user_id_published_at_idx.sql b/packages/db/migrations/0155.do.library_item_user_id_published_at_idx.sql index ddc57ea11..464560b8d 100755 --- a/packages/db/migrations/0155.do.library_item_user_id_published_at_idx.sql +++ b/packages/db/migrations/0155.do.library_item_user_id_published_at_idx.sql @@ -3,4 +3,4 @@ -- Description: Add library_item_user_id_published_at_idx index on library_item table for user_id and published_at -- create index for sorting concurrently to avoid locking -CREATE INDEX CONCURRENTLY IF NOT EXISTS library_item_user_id_updated_at_idx ON omnivore.library_item (user_id, updated_at DESC NULLS LAST); +CREATE INDEX CONCURRENTLY IF NOT EXISTS library_item_user_id_published_at_idx ON omnivore.library_item (user_id, published_at DESC NULLS LAST); diff --git a/packages/db/migrations/0156.do.library_item_user_id_read_at_idx.sql b/packages/db/migrations/0156.do.library_item_user_id_read_at_idx.sql new file mode 100755 index 000000000..1b4d83372 --- /dev/null +++ b/packages/db/migrations/0156.do.library_item_user_id_read_at_idx.sql @@ -0,0 +1,6 @@ +-- Type: DO +-- Name: library_item_user_id_read_at_idx +-- Description: Add library_item_user_id_read_at_idx index on library_item table for user_id and read_at + +-- create index for sorting concurrently to avoid locking +CREATE INDEX CONCURRENTLY IF NOT EXISTS library_item_user_id_read_at_idx ON omnivore.library_item (user_id, read_at DESC NULLS LAST); diff --git a/packages/db/migrations/0156.undo.library_item_user_id_read_at_idx.sql b/packages/db/migrations/0156.undo.library_item_user_id_read_at_idx.sql new file mode 100755 index 000000000..819bd5f8a --- /dev/null +++ b/packages/db/migrations/0156.undo.library_item_user_id_read_at_idx.sql @@ -0,0 +1,9 @@ +-- Type: UNDO +-- Name: library_item_user_id_read_at_idx +-- Description: Add library_item_user_id_read_at_idx index on library_item table for user_id and read_at + +BEGIN; + +DROP INDEX IF EXISTS library_item_user_id_read_at_idx; + +COMMIT; From cf6f15e520a41ea056cde6c4c307697ca5a527b9 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Wed, 10 Jan 2024 17:34:54 +0800 Subject: [PATCH 5/8] add index for sorting by word_count --- .../0157.do.library_item_user_id_word_count_idx.sql | 6 ++++++ .../0157.undo.library_item_user_id_word_count_idx.sql | 9 +++++++++ 2 files changed, 15 insertions(+) create mode 100755 packages/db/migrations/0157.do.library_item_user_id_word_count_idx.sql create mode 100755 packages/db/migrations/0157.undo.library_item_user_id_word_count_idx.sql diff --git a/packages/db/migrations/0157.do.library_item_user_id_word_count_idx.sql b/packages/db/migrations/0157.do.library_item_user_id_word_count_idx.sql new file mode 100755 index 000000000..baef3a5db --- /dev/null +++ b/packages/db/migrations/0157.do.library_item_user_id_word_count_idx.sql @@ -0,0 +1,6 @@ +-- Type: DO +-- Name: library_item_user_id_word_count_idx +-- Description: Add library_item_user_id_word_count_idx index on library_item table for user_id and word_count + +-- create index for sorting concurrently to avoid locking +CREATE INDEX CONCURRENTLY IF NOT EXISTS library_item_user_id_word_count_idx ON omnivore.library_item (user_id, word_count DESC NULLS LAST); diff --git a/packages/db/migrations/0157.undo.library_item_user_id_word_count_idx.sql b/packages/db/migrations/0157.undo.library_item_user_id_word_count_idx.sql new file mode 100755 index 000000000..919a60669 --- /dev/null +++ b/packages/db/migrations/0157.undo.library_item_user_id_word_count_idx.sql @@ -0,0 +1,9 @@ +-- Type: UNDO +-- Name: library_item_user_id_word_count_idx +-- Description: Add library_item_user_id_word_count_idx index on library_item table for user_id and word_count + +BEGIN; + +DROP INDEX IF EXISTS library_item_user_id_word_count_idx; + +COMMIT; From f81ad17fb1ea1c728486c19e43d6fa8c99e7a23f Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Wed, 10 Jan 2024 18:07:58 +0800 Subject: [PATCH 6/8] fix tests --- packages/api/test/resolvers/article.test.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/api/test/resolvers/article.test.ts b/packages/api/test/resolvers/article.test.ts index 090e31208..76398e0d7 100644 --- a/packages/api/test/resolvers/article.test.ts +++ b/packages/api/test/resolvers/article.test.ts @@ -1722,6 +1722,7 @@ describe('Article API', () => { readableContent: '

test 1

', slug: 'test slug 1', originalUrl: `${url}/test1`, + savedAt: new Date(1703880588), }, { user, @@ -1729,6 +1730,7 @@ describe('Article API', () => { readableContent: '

test 2

', slug: 'test slug 2', originalUrl: `${url}/test2`, + savedAt: new Date(1704880589), }, { user, @@ -1736,6 +1738,7 @@ describe('Article API', () => { readableContent: '

test 3

', slug: 'test slug 3', originalUrl: `${url}/test3`, + savedAt: new Date(1705880590), }, ], user.id @@ -1777,6 +1780,7 @@ describe('Article API', () => { readableContent: '

test 1

', slug: 'test slug 1', originalUrl: `${url}/test1`, + savedAt: new Date(1703880588), }, { user, @@ -1784,6 +1788,7 @@ describe('Article API', () => { readableContent: '

test 2

', slug: 'test slug 2', originalUrl: `${url}/test2`, + savedAt: new Date(1704880589), }, { user, @@ -1791,6 +1796,7 @@ describe('Article API', () => { readableContent: '

test 3

', slug: 'test slug 3', originalUrl: `${url}/test3`, + savedAt: new Date(1705880590), }, ], user.id From 1d4d373508cfde970d12ce7c208e213441bb5052 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Thu, 11 Jan 2024 10:21:36 +0800 Subject: [PATCH 7/8] replace the slow postgres trigger function for updating label names --- ...8.do.create_label_names_update_trigger.sql | 30 +++++++++++++++++++ ...undo.create_label_names_update_trigger.sql | 30 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100755 packages/db/migrations/0158.do.create_label_names_update_trigger.sql create mode 100755 packages/db/migrations/0158.undo.create_label_names_update_trigger.sql diff --git a/packages/db/migrations/0158.do.create_label_names_update_trigger.sql b/packages/db/migrations/0158.do.create_label_names_update_trigger.sql new file mode 100755 index 000000000..a27b128b1 --- /dev/null +++ b/packages/db/migrations/0158.do.create_label_names_update_trigger.sql @@ -0,0 +1,30 @@ +-- Type: DO +-- Name: create_label_names_update_trigger +-- Description: Create label_names_update trigger in library_item table + +BEGIN; + +CREATE OR REPLACE FUNCTION update_label_names() +RETURNS TRIGGER AS $$ +BEGIN + UPDATE omnivore.library_item + SET label_names = array_replace(label_names, OLD.name, NEW.name) + WHERE user_id = OLD.user_id AND OLD.name = ANY(label_names); + + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +-- triggers when label name is updated +CREATE TRIGGER label_names_update +AFTER UPDATE ON omnivore.labels +FOR EACH ROW +WHEN (OLD.name <> NEW.name) +EXECUTE FUNCTION update_label_names(); + +-- remove old trigger which is too slow +DROP TRIGGER IF EXISTS entity_labels_update ON omnivore.labels; + +DROP FUNCTION IF EXISTS omnivore.update_entity_labels(); + +COMMIT; diff --git a/packages/db/migrations/0158.undo.create_label_names_update_trigger.sql b/packages/db/migrations/0158.undo.create_label_names_update_trigger.sql new file mode 100755 index 000000000..f0e7145a0 --- /dev/null +++ b/packages/db/migrations/0158.undo.create_label_names_update_trigger.sql @@ -0,0 +1,30 @@ +-- Type: UNDO +-- Name: create_label_names_update_trigger +-- Description: Create label_names_update trigger in library_item table + +BEGIN; + +CREATE OR REPLACE FUNCTION update_entity_labels() +RETURNS trigger AS $$ +BEGIN + -- update entity_labels table to trigger update on library_item table + UPDATE omnivore.entity_labels + SET label_id = NEW.id + WHERE label_id = OLD.id; + + return NEW; +END; +$$ LANGUAGE plpgsql; + +-- triggers when label name is updated +CREATE TRIGGER entity_labels_update +AFTER UPDATE ON omnivore.labels +FOR EACH ROW +WHEN (OLD.name <> NEW.name) +EXECUTE FUNCTION update_entity_labels(); + +DROP TRIGGER IF EXISTS label_names_update ON omnivore.labels; + +DROP FUNCTION IF EXISTS omnivore.update_label_names(); + +COMMIT; From 4cf600e7b09adfe11fffacecb035f2ee0dc9df13 Mon Sep 17 00:00:00 2001 From: Hongbo Wu Date: Thu, 11 Jan 2024 11:45:22 +0800 Subject: [PATCH 8/8] drop old index --- .../migrations/0158.do.create_label_names_update_trigger.sql | 4 ++++ .../0158.undo.create_label_names_update_trigger.sql | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/packages/db/migrations/0158.do.create_label_names_update_trigger.sql b/packages/db/migrations/0158.do.create_label_names_update_trigger.sql index a27b128b1..7fdbf2fd2 100755 --- a/packages/db/migrations/0158.do.create_label_names_update_trigger.sql +++ b/packages/db/migrations/0158.do.create_label_names_update_trigger.sql @@ -27,4 +27,8 @@ DROP TRIGGER IF EXISTS entity_labels_update ON omnivore.labels; DROP FUNCTION IF EXISTS omnivore.update_entity_labels(); +DROP INDEX IF EXISTS omnivore.library_item_saved_at_idx; +DROP INDEX IF EXISTS omnivore.library_item_updated_at_idx; +DROP INDEX IF EXISTS omnivore.library_item_read_at_idx;; + COMMIT; diff --git a/packages/db/migrations/0158.undo.create_label_names_update_trigger.sql b/packages/db/migrations/0158.undo.create_label_names_update_trigger.sql index f0e7145a0..b35b2d57d 100755 --- a/packages/db/migrations/0158.undo.create_label_names_update_trigger.sql +++ b/packages/db/migrations/0158.undo.create_label_names_update_trigger.sql @@ -4,6 +4,10 @@ BEGIN; +CREATE INDEX IF NOT EXISTS library_item_saved_at_idx ON omnivore.library_item (saved_at); +CREATE INDEX IF NOT EXISTS library_item_updated_at_idx ON omnivore.library_item (updated_at); +CREATE INDEX IF NOT EXISTS library_item_read_at_idx ON omnivore.library_item (read_at); + CREATE OR REPLACE FUNCTION update_entity_labels() RETURNS trigger AS $$ BEGIN