From 0dda4ab55a0248fb715ef6a1c84255235899abb1 Mon Sep 17 00:00:00 2001 From: jbranchaud Date: Fri, 24 Feb 2023 10:10:57 -0600 Subject: [PATCH] Add Get A Quick Approximate Count Of A Large Table as a Rails TIL --- README.md | 3 +- ...uick-approximate-count-of-a-large-table.md | 38 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 rails/get-a-quick-approximate-count-of-a-large-table.md diff --git a/README.md b/README.md index e07d18c..2ca60ad 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ pairing with smart people at Hashrocket. For a steady stream of TILs, [sign up for my newsletter](https://crafty-builder-6996.ck.page/e169c61186). -_1285 TILs and counting..._ +_1286 TILs and counting..._ --- @@ -797,6 +797,7 @@ _1285 TILs and counting..._ - [Find Records With Multiple Associated Records](rails/find-records-with-multiple-associated-records.md) - [Force All Users To Sign Out](rails/force-all-users-to-sign-out.md) - [Generating And Executing SQL](rails/generating-and-executing-sql.md) +- [Get A Quick Approximate Count Of A Large Table](rails/get-a-quick-approximate-count-of-a-large-table.md) - [Get ActiveRecord Attribute Directly From Database](rails/get-active-record-attribute-directly-from-database.md) - [Get An Array Of Values From The Database](rails/get-an-array-of-values-from-the-database.md) - [Get An Empty ActiveRecord Relation](rails/get-an-empty-activerecord-relation.md) diff --git a/rails/get-a-quick-approximate-count-of-a-large-table.md b/rails/get-a-quick-approximate-count-of-a-large-table.md new file mode 100644 index 0000000..96284f1 --- /dev/null +++ b/rails/get-a-quick-approximate-count-of-a-large-table.md @@ -0,0 +1,38 @@ +# Get A Quick Approximate Count Of A Large Table + +Let's say our Rails app has a massive `events` table in it's Postgres database. +We might be tempted to reach for an ActiveRecord API method like `Event.count` +to get the number of records in the table. For tables with millions of rows, +this is going to be slow. + +If all we need is an approximate count, there is a faster way that uses some of +PostgreSQL's internal bookkeeping. + +We can request the approximate number of tuples recorded for our table by name. +This query can be processed as raw SQL by the `#execute` method available on +`ActiveRecord::Base.connection`. + +```ruby +ActiveRecord::Base.connection.execute(<<~SQL) + select reltuples::numeric as count + from pg_class + where relname='events'; +SQL +``` + +That is going to spit out the `PG::Result` object which doesn't look like much +on its own. + +``` +# +``` + +If we tack on a couple other methods, we can get the count as our result. + +```ruby +ActiveRecord::Base.connection.execute(<<~SQL).to_a.first["count"].to_i + select reltuples::numeric as count + from pg_class + where relname='events'; +SQL +```