前提
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