Edited at

ActiveRecordで一意データのみカウントするクエリの速度計測

More than 1 year has passed since last update.


前提

Userモデルが以下の状態

レコード数:105100データあった場合

カラム数:20

インデックス:id

rails consoleで実施


1. User.distinct.count

User.distinct.count

**(38.2ms)**
SELECT DISTINCT COUNT(DISTINCT "user"."id") FROM "users"
=> 105100


一番シンプルな書き方だと思いますが、全件検索してカウントしているで速度が出ません


2. User.uniq.count

User.uniq.count

(36.2ms)

SELECT DISTINCT COUNT(DISTINCT "user"."id") FROM "users"

=> 105100


※ActiveRecord::QueryMethods#uniqはRails5.0より非推奨となっており、次の警告が発生します。

DEPRECATION WARNING: uniq is deprecated and will be removed from Rails 5.1 (use distinct instead)


そのため、以降はActiveRecord::QueryMethods#distinctを使用する様になります。


3. User.count('DISTINCT id')

User.count('DISTINCT id')

(33.3ms)

SELECT COUNT(DISTINCT id) FROM "users"

=> 105100


SQL実行時にインデックス対象のテーブルにアクセスする必要がないので高速になる


4. User.group(:id).pluck(:id).count

User.group(:id).pluck(:id).count

(289.5ms)

SELECT "users"."id" FROM "users" GROUP BY "users"."id"

=> 105100


予想外の遅さ。idにインデックス貼ってるのになぜ??


DBアクセスの結果105100件に対してRubyでカウントしている為、遅くなります。


動作環境

Ruby 2.3.1

Rails 4.2.7

DB:PostgreSQL-9.5