Dynamoidを使って全件のレコード数を数える

Dynamoidの1.3.3を使用して検証しています

countメソッドで取得

この方法では「およそ6時間ごとに定期的に更新」というラグを除いてはもっとも良い方法です。ラグがあっても問題ない場合はこの方法で取得するのが一番良いです。

User.count

全件取得して数える

scanでは1MBを超えて取得できないのでページングをする必要があります。

全件取得するためキャパシティを上げておく必要があります(件数が多いと時間がかかります)

キャパシティをかなり消費するので稼働中のシステムに対しては実行しないほうが良いのと、アプリケーションコード内など頻繁に実行されるようなところには向かないです。 (ちなみに僕が使ったのはテーブルのデータ移行時にデータ移行がうまくいったか確認するために使いました)

table_name = :users

count = 0

scan_data = Dynamoid.adapter.client.scan(table_name: table_name)

loop do
  count += scan_data.count
  break unless scan_data.last_evaluated_key

  scan_data = Dynamoid.adapter.client.scan(table_name: table_name, exclusive_start_key: scan_data.last_evaluated_key)
end

カウント用テーブルを作る

countsテーブルのようなテーブルを作り↓のようなレコードを作っておき、usersテーブルが追加されたらカウントアップするという方法です。

パーティションキー
users 0
Dynamoid.adapter.client.update_item(
  table_name: self.table_name,
  key: {tb_name: 'users'},
  update_expression: 'SET #col = #col + :val',
  expression_attribute_names: {"#col" => :num},
  expression_attribute_values: {":val" => 1},
  return_values: 'ALL_NEW'
)

また、アクセスが多いと1レコードにアクセスが集中してしまい更新が出来なくなるので例えば↓のように分散して書き込んで取得する時に合計するという方法を取ることも出来ます。
(取得する時の負荷を抑えたければアプリケーション側でキャッシュを入れたりするのが良いと思います)

パーティションキー
users=0 0
users=1 0
users=2 0