【Solr運用Tips】大量データをインポートするときに気をつけたいポイントまとめ
IT技術
はじめに
Solr を使ったシステムでは、データの追加(import)処理が性能や安定性に大きく影響します。
特に 数十万〜数百万件規模のデータを一括投入するケースでは、単純に add や commit を繰り返すだけでは十分なパフォーマンスが出ず、処理時間が大幅に増加してしまいます。
今回の取り組みでは、大量データインポート時の処理速度を改善することを明確な目的として、Solr の動作特性やリソース負荷を踏まえながら改善を進めました。
この記事では、その過程で実際に効果のあった Solr インポート高速化のための実践的な Tips をまとめて紹介します。
前提
- Solrバージョン:6.6.6(旧系統)
- 使用ライブラリ:
rsolr(Ruby) - 対象データ件数:数十万〜数百万件
- 処理内容:Solrからの取得 → 加工 → Solrコアへ投入
- 処理方式:バッチ単位で複数プロセス並列実行
- 目的:処理の速度の向上
1. commitのタイミングを最適化する
Solrは、addしたデータがすぐには検索結果に反映されません。
明示的にcommitを行うことで初めて検索対象になります。
✅ 悪い例
1records.each do |record|
2 solr.add(record)
3 solr.commit
4end→ 各レコードごとにcommitが走るため、極端に遅くなります。
✅ 良い例
1batch_size = 5000
2records.each_slice(batch_size) do |batch|
3 solr.add(batch)
4 solr.commit
5end- commit回数を減らすことでI/O負荷を軽減。
2. commitWithinを上手く使う
Solrには、commitWithinというパラメータがあります。
rsolrでの記述方法
solr.add(docs, add_attributes: { commitWithin: 20000 })
これは「20秒以内に自動でcommitしてほしい」というリクエストです。
手動commitを減らしたい場合に有効ですが、以下のような特徴があります。
| 項目 | 内容 |
|---|---|
| メリット | commit頻度を自動制御できる |
| デメリット | 実際のcommitタイミングはSolr任せ(制御しにくい) |
| 向いているケース | 少し遅延しても問題ない更新処理やバックグラウンドバッチ |
👉 確実にcommitタイミングを制御したいときは、明示的なcommitの方が安全です。
3. openSearcher=falseで一時的に検索負荷を抑える
大量インポート中に検索も同時に走っている場合、commitごとにSearcherが再オープンされて負荷が増します。
これを防ぐには、openSearcher=falseを指定します。
solr.commit(params: { openSearcher: false })
- 検索の再読み込みを抑止
- インポート処理完了後、最後に一度だけ
openSearcher=trueでcommit
# 最後に反映 solr.commit(params: { openSearcher: true })
これにより、バッチ中の検索負荷を大幅に削減できます。
openSearcher=falseなので、Solr上にデータは存在するが、検索は不可な状態です。Solrのdocsや各処理の整合性を確認しつつ適用しましょう。
4. 並列処理時はcommit衝突に注意
複数プロセスで同一コアに対してcommitを投げると、Solr内部でロックが発生し、
「commit待ち状態」が連鎖的に遅延を引き起こすことがあります。
対策例
- コアごとに処理を分割(都道府県単位など)
- 各プロセスがcommitを行うタイミングをずらす
- 各プロセスとは別の外部リソースで、commitすべきdocsの数をカウントし、カウント数に応じでcommit
- commitWithinと明示commitを併用して、衝突を回避
5. データ追加より更新の方が速い理由
実際に運用していて気づいたのが、既存データの更新は新規追加よりも速いという点です。
理由は、Solrの内部構造(インデックスの差分マージ)にあります。
| 操作 | 処理内容 |
|---|---|
| 新規追加 | 新しいドキュメントIDを作成、term index・posting listの更新が広範囲に発生 |
| 更新 | IDが既に存在するため、削除+差分追加のみで済む |
👉 つまり、更新対象が多いほど「再インデックス範囲」が狭くなり、高速化します。
6. Solrのレプリケーション機能を活用する
処理内容:Solr からのデータ取得 → 加工 → Solr コアへの投入
このパターンで 大量データのインポートを同一 Solr サーバー上で実行すると、Solr からの取得処理が極端に遅くなる場合があります。
原因として、Solr コアへの高頻度の投入(更新)によって検索負荷が上昇するためです。
詳しくは当記事の「3. openSearcher=false で一時的に検索負荷を抑える」を参照してください。
検索処理の負荷が高まると、最初のステップである Solr からの取得が遅延し、結果としてバッチ処理全体のスループットが低下します。
なお、Solr のレプリケーション機能は Master–Slave 方式です。
対策例
処理内容:Solr からのデータ取得 → 加工 → Solr コアへの投入
- Solrからの取得 -> Slaveから取得
- 加工 → アプリケーション
- Solrコアへ投入 -> Masterに対して投入
注意点
Master から Slave への反映には タイムラグ が発生します。
そのため、
- データ整合性に問題が生じないか
- このタイムラグを前提とした実装になっているか
を確認したうえで導入するようにしましょう。
7. パフォーマンス計測のすすめ
commitにかかる時間をログ出力しておくと、負荷のボトルネックを分析しやすくなります。
1start = Time.now
2solr.commit
3Rails.logger.info("[COMMIT TIME] #{Time.now - start} sec")ログ集計で地域別やバッチ別、時間帯別のcommit時間を比較してみましょう。
また、対象の処理件数や、処理の開始や終了時間などを、記録しておくことも大切です。
ログや、記録から分析を行い、パフォーマンスチューニングの方向性を明確にできます。
まとめ
| 項目 | ポイント |
|---|---|
| commit頻度 | バッチ単位(数千〜数万件ごと)にまとめる |
| commitWithin | 自動commitに任せたい時に有効 |
| openSearcher | バッチ中はfalse、最後にtrue |
| 並列処理 | commit衝突に注意、処理タイミングをずらす |
| レプリケーション | 可能であれば、検索と投入を同一サーバーで行わない。 |
| ログ出力 | commit時間を可視化して改善につなげる |
おわりに
Solr への大量データインポートは、一見シンプルな「add + commit」処理に見えますが、
実際には I/O、ロック、index マージなど、複数の要因が複雑に絡み合っています。
そのため、バッチ処理の最適化やリソース管理を丁寧に行うことで、
安定した検索基盤を維持しながら、高速なデータ更新を実現することが可能になります。
また当然ながら、どのストレージにデータを投入する際も、
ストレージ側の仕様を理解したうえで処理を実装することが非常に重要です。
実際、私のプロジェクトでも本記事で紹介した対応を行った結果、
以下のような大きな改善が得られました。
- Solr からの取得件数:約30万件
- Solr コアへの投入件数:約6万件
この条件で 約 2 時間かかっていた処理が、約 20 分まで短縮
次回は、もう少し踏み込んで アプリケーション構成 や
なぜこれらの改善が必要だったのか といった背景も交えつつ、
より実践的な内容をお届けしようと思います。
最後までお読みいただきありがとうございました。
もし似たような課題を抱えている方がいれば、
今回の Tips が少しでもお役に立てば幸いです。
ライトコードでは、エンジニアを積極採用中!
ライトコードでは、エンジニアを積極採用しています!カジュアル面談等もございますので、くわしくは採用情報をご確認ください。
採用情報へ

矢野健太郎です。 バスケットボールとお酒と漫画が好きです。 修行の日々です。





