Skip to content

経路検索のN+1クエリ解消・IPAキャッシュのArc化などクエリ処理のパフォーマンスを改善 - #1585

Merged
TinyKitten merged 5 commits into
devfrom
feature/query-performance
Jul 4, 2026
Merged

経路検索のN+1クエリ解消・IPAキャッシュのArc化などクエリ処理のパフォーマンスを改善#1585
TinyKitten merged 5 commits into
devfrom
feature/query-performance

Conversation

@TinyKitten

@TinyKitten TinyKitten commented Jul 3, 2026

Copy link
Copy Markdown
Member

概要

クエリ処理のパフォーマンス改善。経路検索(get_routes)のN+1クエリ解消、IPAキャッシュのヒット時ディープクローン排除、稼働DBで欠落していた性能インデックスへの恒久対策を行う。

変更の種類

  • バグ修正
  • 新機能
  • データの修正・追加
  • リファクタリング
  • ドキュメント
  • CI/CD
  • その他

変更内容

  • get_routes: 経路候補グループごとに路線を取得していたN+1クエリを、全line_group_cdの一括取得+パーティションに変更。発着駅を含まない候補グループは路線取得・proto変換の前に除外
  • get_routes: TrainTypeに埋め込む路線リストを停車駅ごとに再フィルタ+cloneせず、グループごとに一度だけ構築
  • update_station_vec_with_attributes_inner: ループ末尾で同一入力のget_station_numbersを再計算していた冗長処理を削除し、会社IDを一意化してからIN句クエリへ渡すように変更
  • IPAキャッシュ(domain/ipa.rs)をArc<IpaResult>返却に変更し、キャッシュヒットのたびにTTSセグメントを含む結果全体をディープクローンしていたのを解消
  • 性能インデックス10本(stationsのtrigram×5・point GiST×2、gtfs_stopsのpoint+trigram×2)をcreate_schemaで明示的に作成し、作成後にpg_indexesを照合して欠落をERRORログで可視化(create_table.sqlのDOブロックが例外をNOTICEで握り潰すため、稼働DBでtrigramインデックス5本が欠落し駅名検索が全表スキャンになっていた事例への恒久対策)
  • get_routesの一括取得・候補除外・種別路線構築を検証するテストを追加

テスト

  • cargo fmt --all -- --check が通ること
  • cargo clippy -- -D warnings が通ること
  • cargo testSQLX_OFFLINE=true)が通ること

EXPLAIN ANALYZEで駅名検索がSeq Scan(buffers 625)→Bitmap Index Scan(buffers 36)になることを稼働DBで確認済み。

関連Issue

スクリーンショット(任意)

Summary by CodeRabbit

  • 新機能

    • 路線検索の結果生成が最適化され、関連する路線情報をまとめて扱うことで応答が安定しやすくなりました。
    • 駅・路線・種別の音声読み上げ用データの取り扱いが改善されました。
  • バグ修正

    • 検索用インデックスの不足を検出できるようになり、スキーマ準備時の抜け漏れに気づきやすくなりました。
    • 一部の経路候補で不要な結果が混ざる問題を抑えました。

TinyKitten and others added 4 commits July 4, 2026 03:04
- get_routes: 経路候補グループごとに路線を取得していたN+1クエリを
  一括取得+line_group_cdパーティションに変更。発着駅を含まない
  候補グループは路線取得・proto変換の前に除外する
- get_routes: TrainTypeに埋め込むlinesを停車駅ごとに再フィルタ+
  cloneせず、グループごとに一度だけ構築する
- update_station_vec_with_attributes_inner: ループ末尾で
  get_station_numbersを同一入力で再計算していた冗長処理を削除
- update_station_vec_with_attributes_inner: 会社IDを一意化してから
  IN句クエリに渡すようにし、路線数分の重複バインドを解消
- get_routesの一括取得・候補除外・種別路線構築を検証するテストを追加

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
キャッシュヒットのたびにIpaResult(TTSセグメントのVecを含む)全体を
ディープクローンしていたため、リスト系レスポンスでは駅・路線・種別
ごとに数個のStringアロケーションが発生していた。Arc<IpaResult>を
返す形にし、proto変換時に必要なフィールドだけをクローンする。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
create_table.sqlのDOブロックは拡張が使えない環境向けに例外を
NOTICEで握り潰すため、インデックス作成に失敗しても起動ログからは
分からない。実際に稼働DBでtrigramインデックス5本だけが欠落し、
駅名検索が毎回全表スキャンになる事例があった。

必要な拡張はcreate_schema冒頭で必須として作成済みのため、
性能インデックスはスキーマ適用後に明示的に作成し直し、作成後に
pg_indexesを検証して欠落があればERRORログで可視化する。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@TinyKitten TinyKitten self-assigned this Jul 3, 2026
@github-actions github-actions Bot added feature 要望対応や課題解決 deploy-dev and removed feature 要望対応や課題解決 labels Jul 3, 2026
@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

IPA計算キャッシュがArc共有方式に変更され、DTO変換(line/station/train_type/tts)が参照・クローンベースに更新された。get_routesは経路グループの事前フィルタと路線の一括取得に再構成され、テストが追加された。スキーマ作成時にパフォーマンスインデックスの作成・検証処理が追加された。

Changes

IPAキャッシュ共有化・ルート最適化・インデックス検証

Layer / File(s) Summary
IPAキャッシュのArc化
stationapi/src/domain/ipa.rs
キャッシュ値がArcとなり、共通のcached_lookup関数で読み取り/書き込みロックによるキャッシュ取得・生成処理が統一され、compute_ipa_cached/compute_line_ipa_cachedの返り値がArcに変更された。
DTO変換の参照/クローン化
stationapi/src/use_case/dto/tts.rs, stationapi/src/use_case/dto/line.rs, stationapi/src/use_case/dto/station.rs, stationapi/src/use_case/dto/train_type.rs
to_proto_tts_segmentsの引数が&[TtsNameSegment]となり、各DTO変換でipa由来のフィールド取得がムーブからクローン・参照渡しに変更された。
get_routes路線一括取得とフィルタ再構成
stationapi/src/use_case/interactor/query.rs
get_routesが発着駅を含む経路グループを先にフィルタし、line_group_cdを一意化して路線を一括取得・パーティションする方式へ変更され、company_idsの重複排除追加、不要なstation_numbers再計算削除、対応するテストが追加された。
スキーマ作成時のインデックス検証
stationapi/src/import.rs
create_schema()にパフォーマンスインデックス定数を追加し、実行後にpg_indexesで存在検証し欠落をエラーログ出力する処理を追加した。

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant get_routes
  participant RouteGroups
  participant LineRepository

  Client->>get_routes: from_station_id, to_station_id
  get_routes->>RouteGroups: 発着駅を含むグループのみ抽出
  get_routes->>get_routes: line_group_cdを一意化
  get_routes->>LineRepository: get_by_line_group_id_vec_for_routesを一括呼び出し
  LineRepository-->>get_routes: Line一覧
  get_routes->>get_routes: line_group_cdでパーティション
  get_routes-->>Client: 経路候補(TrainType/stops付き)
Loading
sequenceDiagram
  participant Caller
  participant compute_ipa_cached
  participant cached_lookup
  participant STATION_IPA_CACHE

  Caller->>compute_ipa_cached: name_katakana, name_roman
  compute_ipa_cached->>cached_lookup: 検索要求
  cached_lookup->>STATION_IPA_CACHE: 読み取りロックでヒット確認
  alt キャッシュヒット
    STATION_IPA_CACHE-->>cached_lookup: Arc<IpaResult>クローン
  else キャッシュミス
    cached_lookup->>cached_lookup: compute()実行
    cached_lookup->>STATION_IPA_CACHE: 書き込みロックで挿入
  end
  cached_lookup-->>Caller: Arc<IpaResult>
Loading

Possibly related PRs

  • TrainLCD/StationAPI#1532: stationapi/src/domain/ipa.rscompute_line_ipa_cachedGrpcLine.name_ipa生成に関わる変更で、本PRのキャッシュ/返り値型変更と同じ出力経路に影響する。
  • TrainLCD/StationAPI#1543: compute_ipa_cached/compute_line_ipa_cachedのキャッシュ入出力・シグネチャを扱う点で本PRのArc化と直接関連する。
  • TrainLCD/StationAPI#1548: compute_line_ipa_cachedのメモ化・生成フローを直接扱っており、戻り値の扱いがコードレベルで衝突し得る。

Suggested labels: fix

Poem

IPAはArcに包まれて跳ねる 🐇
キャッシュの森を軽やかに駆ける
経路たちも一括まとめて選ばれて
インデックスの見張り番も新登場
うさぎは今日も静かに祝う 🥕✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed 主要な変更点である経路検索のN+1解消とIPAキャッシュのArc化を簡潔に表しています。
Description check ✅ Passed 必要な見出しが揃っており、概要・変更内容・テストが具体的に記載されています。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/query-performance

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the feature 要望対応や課題解決 label Jul 4, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
stationapi/src/import.rs (1)

41-88: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

PERFORMANCE_INDEXEScreate_table.sql と二重管理しないようにする
現状は同内容ですが、ここは create_table.sql の同名DDLを手書きで複製しているため、片方だけ更新されると性能インデックスの定義がずれます。単一ソース化するか、少なくとも差分検出を入れておくと安全です。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@stationapi/src/import.rs` around lines 41 - 88, The PERFORMANCE_INDEXES list
in import.rs is duplicating the index DDL already defined in create_table.sql,
so the two sources can drift. Refactor the index definitions so there is a
single source of truth, or add a check in the import/create flow that compares
the names and SQL for PERFORMANCE_INDEXES against the SQL file before applying
them. Use the PERFORMANCE_INDEXES constant and the create_table.sql-driven table
setup path as the main anchors when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@stationapi/src/import.rs`:
- Around line 41-88: The PERFORMANCE_INDEXES list in import.rs is duplicating
the index DDL already defined in create_table.sql, so the two sources can drift.
Refactor the index definitions so there is a single source of truth, or add a
check in the import/create flow that compares the names and SQL for
PERFORMANCE_INDEXES against the SQL file before applying them. Use the
PERFORMANCE_INDEXES constant and the create_table.sql-driven table setup path as
the main anchors when making the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b30b0298-4ed7-42f6-aa07-59a4b282f3b5

📥 Commits

Reviewing files that changed from the base of the PR and between 4392f41 and 61f75e3.

📒 Files selected for processing (7)
  • stationapi/src/domain/ipa.rs
  • stationapi/src/import.rs
  • stationapi/src/use_case/dto/line.rs
  • stationapi/src/use_case/dto/station.rs
  • stationapi/src/use_case/dto/train_type.rs
  • stationapi/src/use_case/dto/tts.rs
  • stationapi/src/use_case/interactor/query.rs

@TinyKitten
TinyKitten merged commit 30366a1 into dev Jul 4, 2026
11 checks passed
@TinyKitten
TinyKitten deleted the feature/query-performance branch July 4, 2026 02:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

deploy-dev feature 要望対応や課題解決

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant