近傍バス停の絞り込みを件数の上限より先に行う - #1648
Conversation
get_bus_stops_near_stations は半径以内のバス停を距離順に limit_per_station 件へ切り詰めてから、路線を引けるか (かつ路線が有効か) を見ていた。移行前の SQL が LATERAL 側で LIMIT を掛けてから lines を JOIN していたのをそのまま 写したものだが、路線を引けないバス停や廃止路線のバス停が上限の枠を埋めると、 その分だけ採用件数が減る。 先に路線で絞り、有効なものが limit_per_station 件そろった時点で打ち切る。 座標の順・距離順という並びは変わらない。 あわせて index::within_radius と docs/nearby-bus-stops.md の、絞り込みと 上限の順序を述べた記述を実装に合わせた。
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Warning Billing warning: we have not been able to collect payment for this subscription for more than 72 hours. Please update the payment method or pay any pending invoices in Billing to avoid service interruption. Comment |
092b418
into
claude/train-route-bottleneck-wgz31w
trainRoute は要求区間の長さに関係なく 1 リクエスト約 290ms かかっていた。 ボトルネックは 2 か所。 - 系統の全駅に付帯情報を付けてから要求区間へ切り出していた。3 駅を要求しても 250 駅ぶんを組み立てるため、区間の長さに費用が比例しない。付帯情報の付与は 駅ごとに独立しているので、切り詰めてから付けるよう順序を入れ替えた。 O(系統の駅数) から O(要求区間の駅数) へ。 - 近傍バス停の検索が駅ごとの全件走査だった。種別ごとのグリッド索引 (0.05 度のマスを CSR で保持) を入れ、半径を広げながら探して打ち切る。 O(駅の総数) から O(半径内のマス) へ。stationsNearby にも効く。 本番相当のデータ (41,148 駅 / うちバス停 30,000) での計測: 250 駅 (東京〜出雲市) 290.4ms -> 14.7ms 13 駅 293.9ms -> 2.59ms 3 駅 295.0ms -> 1.39ms あわせて、索引化の過程で見つかった不具合を修正する。 - stationsNearby の並びが近い順という仕様に反し、transportType 未指定のとき 鉄道駅が常にバス停より先に来ていた。移行前の SQL から続く挙動。 - 近傍バス路線が、無効な路線のバス停に上限の枠を埋められて欠落していた (#1648)。有効な路線を持つバス停だけを数えて打ち切る。 - 距離が同着の場合の並びを station_cd 昇順に決め切る。不安定ソート任せで どの路線の行が先に来るか不定だった。 索引は外部入力 (GTFS) の外れ値に対して頑健にしてある。NaN・無限大・WGS84 の 範囲外を索引から外し、マス数に上限を設けて超える場合はマスを粗くする。 nearest / within_radius は入口で無効な座標・半径を弾く (lat が NaN だと 探索半径を無限大まで広げても打ち切れず、1 リクエストで Worker が固まる)。 Worker crate の索引はネイティブでも動くため make test へ追加した。
概要
#1647 の後続 PR です(base は
claude/train-route-bottleneck-wgz31w)。get_bus_stops_near_stationsが、半径以内のバス停を距離順にlimit_per_station件へ切り詰めてから路線を引いていたため、路線を引けないバス停や廃止路線 (e_status != 0) のバス停が上限の枠を埋めると、その分だけ採用件数が減っていました。絞り込みを先に行い、有効なものがlimit_per_station件そろった時点で打ち切るようにします。変更の種類
変更内容
src/repository.rs:get_bus_stops_near_stationsを「半径以内を近い順に見る → 有効な路線を持つものだけ残す →limit_per_station件で打ち切る」順序に変更。並びは従来どおり指定された座標の順、その中では距離順。src/index.rs:within_radiusの doc コメントにあった「呼び出し側が件数を確定させてから路線で絞る」を実装に合わせて修正。docs/nearby-bus-stops.md: 「最大50件のバス停候補を取得し、その中から300m以内のものをフィルタリング」という記述を、trainRoute のボトルネックを解消し stationsNearby の並びを距離順に修正 #1647 以降の実装(半径で切ってから採用)に合わせて更新。従来の挙動との関係
この順序は移行前の SQL をそのまま写したものでした。
LATERAL側でLIMITを掛けてからlinesをJOINしていたため、路線が引けない行はそこで落ちるだけで、その枠は埋め直されません。LATERAL ( SELECT s.* FROM stations s WHERE s.e_status = 0 AND s.transport_type = $5 ORDER BY point(s.lat, s.lon) <-> point(ic.lat, ic.lon) LIMIT $4 ) s JOIN lines AS l ON s.line_cd = l.line_cd AND l.e_status = 0data/*.csvにはバスデータが含まれないためこのリポジトリのデータでは差分は出ませんが、鉄道側にはe_status != 0の路線に紐づく駅が 15 件あり、バス側で同じ状態が起きれば近傍バス停・近傍バス路線が黙って減ります。GTFS 由来のバス停と路線が食い違わない限り応答は変わりません。テスト
実行したコマンドと結果:
make fmt— 成功make clippy— 成功(wasm32 ターゲットを含む)make test— 成功(418 件)make check— 成功get_bus_stops_near_stationsは埋め込み CSV から作る静的な索引を直接引くため、廃止路線のバス停を差し込んだケースの単体テストは追加していません(バスデータを含むフィクスチャが必要になります)。make fmtが通ることmake clippyが通ること(wasm32 ターゲットを含む)make testが通ること関連Issue
スクリーンショット(任意)
Generated by Claude Code