【Rails】activerecord-importで発行されるSQL
はじめに
本記事では、activerecord-import
というGemを使用した場合と使用しない場合のSQLの違いとその影響について解説します。activerecord-import
は、大量のデータを効率的にデータベースに挿入するためのツールであり、特にパフォーマンスの向上が期待できます。これを利用することで、データベース操作の最適化が可能になります。
activerecord-import
を使用する場合と使用しない場合のSQLの違い
activerecord-import
を使用する場合と使用しない場合のSQLの違いは、主に以下の4つです。
- SQL文の数
- トランザクション
- バリデーションとユニーク制約の処理
- パフォーマンス
SQL文の数
使用しない場合
通常のActiveRecordを使用すると、各レコードごとに個別のINSERT文が生成されます。例えば、100件のレコードを挿入する場合、100個のINSERT文が実行されます。
INSERT INTO books (title, author) VALUES ('Book 1', 'Author 1');
INSERT INTO books (title, author) VALUES ('Book 2', 'Author 2');
...
INSERT INTO books (title, author) VALUES ('Book 100', 'Author 100');
使用する場合
activerecord-import
を使用すると、一つのINSERT文で複数のレコードを挿入できます。このため、SQL文の数が大幅に減少します。
INSERT INTO books (title, author) VALUES
('Book 1', 'Author 1'),
('Book 2', 'Author 2'),
...
('Book 100', 'Author 100');
トランザクション
使用しない場合
通常のActiveRecordを使用すると、各INSERT文が個別のトランザクションとして処理されることがあります。
BEGIN;
INSERT INTO books (title, author) VALUES ('Book 1', 'Author 1');
COMMIT;
BEGIN;
INSERT INTO books (title, author) VALUES ('Book 2', 'Author 2');
COMMIT;
使用する場合
activerecord-import
を使用すると、全てのINSERT文を一つのトランザクションでまとめて実行することが可能です。
BEGIN;
INSERT INTO books (title, author) VALUES
('Book 1', 'Author 1'),
('Book 2', 'Author 2'),
...
('Book 100', 'Author 100');
COMMIT;
バリデーションとユニーク制約の処理
使用しない場合
通常のActiveRecordを使用すると、各レコードごとに個別にバリデーションが実行され、ユニーク制約のチェックも個別に行われます。
SELECT 1 FROM books WHERE title = 'Book 1' LIMIT 1;
INSERT INTO books (title, author) VALUES ('Book 1', 'Author 1');
SELECT 1 FROM books WHERE title = 'Book 2' LIMIT 1;
INSERT INTO books (title, author) VALUES ('Book 2', 'Author 2');
使用する場合
activerecord-import
では、バリデーションをスキップするオプションがあり、データベース側でユニーク制約を処理することも可能です。これにより、パフォーマンスがさらに向上します。
INSERT INTO books (title, author) VALUES
('Book 1', 'Author 1'),
('Book 2', 'Author 2')
ON CONFLICT (title) DO NOTHING;
パフォーマンス
activerecord-import
を使用することで、大量のデータを挿入する際のパフォーマンスが大幅に向上します。例えば、50万行のデータを挿入する場合、通常のActiveRecordを使用すると数時間かかる処理が、activerecord-import
を使用すると3分以内に完了したという報告もあります。
こうした違いにより、activerecord-import
は大量のデータを効率的に挿入する必要がある場合に特に有効です。ただし、小規模なデータセットや、個々のレコードに対して複雑な処理が必要な場合は、通常のActiveRecordの方が適している場合もありそうです。
参考資料
Discussion