ABR-Geocoderを試す
目的
ABR Geocoder 概要
デジタル庁が提供する、日本国内の住所文字列を正規化し、緯度経度を返すジオコーディングツール。アドレス・ベース・レジストリ(全国の住所マスターデータ)をデータソースとし、政府により月次で更新されるため信頼性が高い。MITライセンスで提供され、オフライン(外部API利用なし)で動作させることができる
主な機能
技術仕様
特徴
ローカルでの起動方法
# Node.js 20以上が必要
npm install -g @digital-go-jp/abr-geocoder
# データのダウンロード(全国データ)
abrg download
# 特定地域のみダウンロード(例:東京都)
abrg download -c 130001
# RESTサーバーとして起動
abrg serve start
# ポートを指定して起動(デフォルトは3000)
abrg serve start -p 8080
ダウンロードの実行について
ローカルでの実行なので、ネットワーク、実行環境にもよるだろうが、ちょうど1hほどかかった
❯ abrg download --debug
download: 1:00:53.900 (h:mm:ss.mmm)
実行してみる
curlでの実行
早くも面倒になったのでテストとして向いている住所での実行をClaude + playwright mcpにお任せした結果
- 千代田区1-9-1 東京駅の出力結果として、othersが-1 東京駅 となる
- 実際には1ではグラントウキョウノースタワー、2ではグラントウキョウサウスタワーとなっている模様
- 特に大規模ビルの場合、街区番号(1-9)までしか登録されていない可能性
→ ビル名、部屋番号などの抽出も完璧にはできないかも
スコアの傾向
入力パターン | score | match_level | 特徴 |
千代田区霞が関1−3−1 | 0.57 | residential_block | 都道府県省略 |
東京都港区六本木6-10-1 | 0.87 | residential_block | 都道府県明記 |
千代田区永田町1-7-1 | 0.57 | residential_block | 都道府県省略 |
札幌市中央区北3条西6丁目 | 0.82 | machiaza_detail | 都道府県省略だが高スコア |
京都市中京区寺町通御池上る上本能寺前町488 | 0.88 | parcel | 複雑な京都住所だが高スコア |
澁谷区澁谷1-1-1 | 0.5 | residential_detail | 旧字体使用 |
千代田区丸の内1-9-1 東京駅 | 0.7 | residential_block | ビル名付き |
千代田区 | 0.58 | city | 市区町村のみ |
大阪市中央区大手前2-1-22 | 0.74 | residential_detail | 都道府県省略 |
都道府県が省略されている場合、一貫して低めのスコア(0.5〜0.6台)になる傾向
- 旧字体(澁谷)→ 0.5(最低値)
- 標準的な表記 → 0.7〜0.9
- 0.8以上: そのまま信頼
- 0.6〜0.8: 念のため確認推奨
- 0.6未満: 入力の見直しを促す
ECRでABR Geocoderを使用する場合の方針
デフォルトで~/.abr-geocoder に関連ファイルが保存される。
このフォルダのサイズは、全国データをdownload後で58GB程度
❯ du -sk .abr-geocoder | awk '{print $1/1024 " MiB"}' ─╯
57419.9 MiB
SQLiteとマウントファイルシステムのパフォーマンス影響
docker image build時に全国データを含んだコンテナを生成するのは現実的ではなく(ECRだとImage Layerの最大サイズ制限10GBなので実質的に無理)、ABR Geocoderは内部的にSQLiteを使用しているため、ストレージタイプの選択はパフォーマンスに直結する
Claude いわく
SQLiteの特性
ストレージタイプの影響
ストレージ選択による影響
ストレージタイプ | レスポンス時間(目安) | 推奨用途 |
EBS gp3 | 20-100ms | 本番環境 |
EFS | 50-500ms | 複数コンテナ共有時 |
FSx for Lustre | 15-80ms | 高性能要求時 |
SQLite最適化設定
# SQLiteのパフォーマンスチューニング
export SQLITE_TMPDIR=/dev/shm # メモリ上の一時ファイル
export PRAGMA_CACHE_SIZE=10000 # キャッシュサイズ増加
export PRAGMA_MMAP_SIZE=268435456 # メモリマップサイズ
アーキテクチャ
EBSマウント(推奨)
デプロイ戦略(データ更新)
EBSのボリュームは単一Fargate Taskにしかアタッチできない制約あり(そもそもSQLite接続するので別にした方がよさそうではある)
以下の構成でコスト最適化 / デプロイ時間短縮化 / 可用性担保ができそう
まとめ
以下の構成がよさそう
- データ更新の反映とabr-geocoder更新をデプロイで実施する
abrg update checkの実行
更新可能データの取得基準がわからないが、更新対象ファイルがあると毎回出てしまった。
この時の処理時間は3.5min
❯ abrg update-check ─╯
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0% | 0/1total = 10698
利用可能な更新データ(3793)があります。
続けてデータをダウンロードしますか? [Y/N] y
~ 3m 24s 14:54:00 ─╮
❯ abrg update-check -y ─╯
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 0% | 0/1total = 10698
利用可能な更新データ(3793)があります。
api実行負荷テスト
直列実行で、ローカル起動したときのテスト、100回計測の平均値を100回計測
#!/bin/bash
# 負荷テストスクリプト - 100回の平均時間を100回測定
echo "負荷テスト開始: 100回の平均時間を100回測定します"
echo "URL: http://localhost:3000/geocode?address=東京都千代田区霞が関1-3-1"
echo "----------------------------------------"
# 100回の測定を実行
for round in {1..100}; do
total_time=0
# 100回のリクエストを実行して時間を測定
for i in {1..100}; do
# timeコマンドの出力をファイルに保存
{ time curl -s "http://localhost:3000/geocode?address=東京都千代田区霞が関1-3-1" > /dev/null; } 2> temp_time.txt
# real時間を抽出(秒単位)
real_time=$(grep "real" temp_time.txt | awk '{print $2}' | sed 's/m/ * 60 + /' | sed 's/s//' | bc -l)
total_time=$(echo "$total_time + $real_time" | bc -l)
done
# 平均時間を計算
average_time=$(echo "scale=4; $total_time / 100" | bc -l)
# 結果を出力
echo "ラウンド $round: 平均応答時間 = ${average_time}秒"
# 一時ファイルを削除
rm -f temp_time.txt
done
echo "----------------------------------------"
echo "すべての測定が完了しました"
data
0.015 - 0.060s程度で実行される。あくまでローカル実行なので参考程度。リソースのモニタリングもしていない。
並列処理についてgithubに言及があるため、ランタイムはnode.jsのようだがクラスター使用しているかも。その場合、CPU数は上げておいた方がいい可能性がある。また、memory使用量もモニタリングして決定した方がよさそう。このあたりは本格的に負荷テストを行なって確認した方がよい