この記事を書いた背景
RailsのAPIモードで開発していたのですが、動作確認のためステージング環境にテストデータを大量に作成する必要がありました。
その際、Railsコンソールからデータを増やそうと思いeach
で繰り返しデータの生成を実行したのですが、herokuのプランの都合上1時間に発行できるクエリ数が3,600に限られており、それがオーバーしたようでデータの作成が途中で終わってしまいました(泣)
しかも、一度クエリの上限数を超えると1時間ほどDBにアクセスできなくなるという問題も、、、
(現在は有料プランに切り替えたので恐らく問題ないですが、当時は無料プランだったためこうした制限に引っ掛かりました)
参考:https://zenn.dev/ttskch/articles/905ae809e29504
- 急に有料プランに切り替えたくても自社持ちの費用でないため承認まで時間がかかる可能性があること、
- リリースまで時間がなく、なるべくすぐにステージング環境で動作検証をしたかったこと
このような理由から、herokuが復旧後、SQLでバルクインサートを行い発行するクエリ数を最小限にしつつテストデータを大量作成する方法を取りました。
やったこと
- 増やしたいデータの洗い出し
- sequel aceを使いdumpデータをexport
- テキストエディタなどでdumpを開き、書いてあるINSERT文を参考に必要に応じてVALUESw変数に置き換え
- macのターミナルでrubyを使いINSERTする内容を大量に複製する
(別に繰り返しできれば言語はなんでもいい) - 複製した内容をINSERT文の中に入れてSQLでクエリ実行
とざっくりこんな感じです。
INSERT文
INSERT INTO テーブル名
(カラム名1, カラム名2, ...)
VALUES
(値1, 値2, ...); --VALUESの値をRubyを使って複製するイメージ
Rubyを使って複製
- 例:100回複製する場合
- ターミナルを使い
irb
と入力しenter(Rubyがインストールされていることが前提) -
irb(main):001
という表示が出てきたらRubyが実行できます
(1..100).each do |i| #1以上100以下でiを繰り返していく
puts "('name_#{i}', 'email_#{i}@example.com')," #この行が範囲指定した数だけ複製される
end
- ターミナルで複製された結果をコピペしてVALUESに入れる
結果
INSERT INTO テーブル名
(カラム名1, カラム名2, ...)
VALUES
('name_1', 'email_1@example.com', ...),
('name_2', 'email_2@example.com', ...), -- 途中の,を忘れないように
...
('name_100', 'email_100@example.com', ...); --最後は;を忘れないように
やってみた感想
- コピペの手間もあるし普通に面倒
- でもこういう仕方ない場合に有効だな〜
- プログラムに働かせるということを覚えた
- ちなみに自分でこの方法を考えたっぽく言ってますが、教えてもらいました