LoginSignup
5
6

More than 5 years have passed since last update.

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

Last updated at Posted at 2017-08-05

前提

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

5
6
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6