From 93f6e935a880cac687c7abec0f40a5734c937499 Mon Sep 17 00:00:00 2001 From: evazion Date: Thu, 18 Feb 2021 04:06:11 -0600 Subject: [PATCH] search: fix underestimation of page count for blank searches. Bug: In Postgres 13, getting the count of a blank search underestimated the page count by a large margin (~700,000 posts). The query we were executing was this: EXPLAIN (FORMAT JSON) SELECT * FROM posts ORDER BY id DESC The `ORDER BY id DESC` clause triggered a parallel seq scan query plan in Postgres 13, which for some reason causes Postgres to underestimate the row count by large amount in each parallel branch. Getting rid of the ORDER BY clause makes it do a regular seq scan, which gives an accurate estimate. --- app/logical/explain_parser.rb | 11 ++++++++++- app/logical/post_query_builder.rb | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/logical/explain_parser.rb b/app/logical/explain_parser.rb index c9346b456..2afc6f57f 100644 --- a/app/logical/explain_parser.rb +++ b/app/logical/explain_parser.rb @@ -1,5 +1,10 @@ -class ExplainParser < Struct.new(:sql) +class ExplainParser extend Memoist + attr_reader :relation + + def initialize(relation) + @relation = relation + end def query_plan result = ApplicationRecord.connection.select_one("EXPLAIN (FORMAT JSON) #{sql}") @@ -11,5 +16,9 @@ class ExplainParser < Struct.new(:sql) query_plan["Plan Rows"] end + def sql + relation.reorder(nil).to_sql + end + memoize :query_plan end diff --git a/app/logical/post_query_builder.rb b/app/logical/post_query_builder.rb index f84506a1e..5c0b5f5e1 100644 --- a/app/logical/post_query_builder.rb +++ b/app/logical/post_query_builder.rb @@ -851,7 +851,7 @@ class PostQueryBuilder end def estimated_row_count - ExplainParser.new(build.to_sql).row_count + ExplainParser.new(build).row_count end def cached_count