From eccc699b0caf09c36993d3d17abcce01a02eb5a1 Mon Sep 17 00:00:00 2001 From: Sean Griffin Date: Tue, 14 May 2019 10:58:57 -0600 Subject: [PATCH] Fix performance regression on crate search A major performance regression was introduced by #1560, as it didn't introduce the appropriate index and the query is now falling back to a sequential scan. This has caused the query to increase from 12ms on average to 756ms on average. This introduces the appropriate index, bringing performance back to its previous levels. Original Query --- ``` QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Limit (cost=180.26..180.26 rows=1 width=881) (actual time=0.509..0.509 rows=0 loops=1) -> WindowAgg (cost=180.26..180.26 rows=1 width=881) (actual time=0.508..0.508 rows=0 loops=1) -> Sort (cost=180.26..180.26 rows=1 width=873) (actual time=0.506..0.506 rows=0 loops=1) Sort Key: ((replace(lower((crates.name)::text), '-'::text, '_'::text) = 'crates_io_test'::text)) DESC, crates.name Sort Method: quicksort Memory: 25kB -> Nested Loop Left Join (cost=174.19..180.25 rows=1 width=873) (actual time=0.502..0.502 rows=0 loops=1) -> Bitmap Heap Scan on crates (cost=174.13..176.19 rows=1 width=864) (actual time=0.502..0.502 rows=0 loops=1) Recheck Cond: ((plainto_tsquery('crates-io-test'::text) @@ textsearchable_index_col) OR (replace(lower((name)::text), '-'::text, '_'::text) = 'crates_io_test'::text)) -> BitmapOr (cost=174.13..174.13 rows=1 width=0) (actual time=0.500..0.500 rows=0 loops=1) -> Bitmap Index Scan on index_crates_name_search (cost=0.00..172.05 rows=1 width=0) (actual time=0.475..0.475 rows=0 loops=1) Index Cond: (plainto_tsquery('crates-io-test'::text) @@ textsearchable_index_col) -> Bitmap Index Scan on index_crates_name (cost=0.00..2.08 rows=1 width=0) (actual time=0.025..0.025 rows=0 loops=1) Index Cond: (replace(lower((name)::text), '-'::text, '_'::text) = 'crates_io_test'::text) -> Index Scan using recent_crate_downloads_crate_id on recent_crate_downloads (cost=0.06..4.06 rows=1 width=12) (never executed) Index Cond: (crate_id = crates.id) Planning Time: 0.658 ms Execution Time: 0.565 ms ``` New Query w/o this commit --- ``` QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Limit (cost=4614.84..4614.86 rows=3 width=881) (actual time=225.720..225.720 rows=0 loops=1) -> WindowAgg (cost=4614.84..4614.86 rows=3 width=881) (actual time=225.719..225.719 rows=0 loops=1) -> Sort (cost=4614.84..4614.84 rows=3 width=873) (actual time=225.717..225.717 rows=0 loops=1) Sort Key: ((replace(lower((crates.name)::text), '-'::text, '_'::text) = 'crates_io_test'::text)) DESC, crates.name Sort Method: quicksort Memory: 25kB -> Nested Loop Left Join (cost=0.06..4614.84 rows=3 width=873) (actual time=225.710..225.711 rows=0 loops=1) -> Seq Scan on crates (cost=0.00..4602.65 rows=3 width=864) (actual time=225.709..225.709 rows=0 loops=1) Filter: ((plainto_tsquery('crates-io-test'::text) @@ textsearchable_index_col) OR (replace(lower((name)::text), '-'::text, '_'::text) ~~ 'crates_io_test'::text)) Rows Removed by Filter: 25739 -> Index Scan using recent_crate_downloads_crate_id on recent_crate_downloads (cost=0.06..4.06 rows=1 width=12) (never executed) Index Cond: (crate_id = crates.id) Planning Time: 0.536 ms Execution Time: 225.774 ms ``` New Query after this commit ``` QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Limit (cost=80.32..80.34 rows=3 width=881) (actual time=0.466..0.466 rows=0 loops=1) -> WindowAgg (cost=80.32..80.34 rows=3 width=881) (actual time=0.465..0.465 rows=0 loops=1) -> Sort (cost=80.32..80.32 rows=3 width=873) (actual time=0.464..0.464 rows=0 loops=1) Sort Key: ((replace(lower((crates.name)::text), '-'::text, '_'::text) = 'crates_io_test'::text)) DESC, crates.name Sort Method: quicksort Memory: 25kB -> Nested Loop Left Join (cost=62.11..80.32 rows=3 width=873) (actual time=0.459..0.459 rows=0 loops=1) -> Bitmap Heap Scan on crates (cost=62.05..68.13 rows=3 width=864) (actual time=0.458..0.458 rows=0 loops=1) Recheck Cond: ((plainto_tsquery('crates-io-test'::text) @@ textsearchable_index_col) OR (replace(lower((name)::text), '-'::text, '_'::text) ~~ 'crates_io_test'::text)) Rows Removed by Index Recheck: 22 Heap Blocks: exact=21 -> BitmapOr (cost=62.05..62.05 rows=3 width=0) (actual time=0.255..0.255 rows=0 loops=1) -> Bitmap Index Scan on index_crates_name_search (cost=0.00..28.05 rows=1 width=0) (actual time=0.103..0.103 rows=0 loops=1) Index Cond: (plainto_tsquery('crates-io-test'::text) @@ textsearchable_index_col) -> Bitmap Index Scan on sgrif_testing (cost=0.00..34.00 rows=3 width=0) (actual time=0.151..0.151 rows=22 loops=1) Index Cond: (replace(lower((name)::text), '-'::text, '_'::text) ~~ 'crates_io_test'::text) -> Index Scan using recent_crate_downloads_crate_id on recent_crate_downloads (cost=0.06..4.06 rows=1 width=12) (never executed) Index Cond: (crate_id = crates.id) Planning Time: 0.476 ms Execution Time: 0.528 ms ``` --- migrations/2019-05-14-165316_index_crate_name_for_like/down.sql | 2 ++ migrations/2019-05-14-165316_index_crate_name_for_like/up.sql | 2 ++ 2 files changed, 4 insertions(+) create mode 100644 migrations/2019-05-14-165316_index_crate_name_for_like/down.sql create mode 100644 migrations/2019-05-14-165316_index_crate_name_for_like/up.sql diff --git a/migrations/2019-05-14-165316_index_crate_name_for_like/down.sql b/migrations/2019-05-14-165316_index_crate_name_for_like/down.sql new file mode 100644 index 00000000000..002913fc445 --- /dev/null +++ b/migrations/2019-05-14-165316_index_crate_name_for_like/down.sql @@ -0,0 +1,2 @@ +DROP INDEX index_crates_name_tgrm; +DROP EXTENSION pg_trgm; diff --git a/migrations/2019-05-14-165316_index_crate_name_for_like/up.sql b/migrations/2019-05-14-165316_index_crate_name_for_like/up.sql new file mode 100644 index 00000000000..f188a9cd166 --- /dev/null +++ b/migrations/2019-05-14-165316_index_crate_name_for_like/up.sql @@ -0,0 +1,2 @@ +CREATE EXTENSION pg_trgm; +CREATE INDEX index_crates_name_tgrm ON crates USING gin (canon_crate_name(name) gin_trgm_ops);