「とりあえずやってみて」と渡された移行ツール

この案件で最初から 「大量データを高速に移行するツールを作ろう」 と考えていたわけではありません。

もともと存在していたのは、 1件のデータを投入することを前提にした 既存の移行ツールでした。

そのツールを引き継ぐことになったのですが、 問題はここからでした。

引き継いだ時点の状況

・大量データを想定していない
・仕様書が十分にない
・処理の詳細を説明できる知見者がいない
・元の担当者もいない

つまり、何をどう直せばいいのかも、 最初から明確だったわけではありません。

まず大量データを流してみた

仕様書を眺めていても、 実際にどこが問題になるのかは分かりません。

そこで、 とりあえず実際のデータを使って 移行処理を動かしてみました。

すると、 そこで初めて大きな問題が見えてきました。

移行完了までの見込み

約2年半

1件のデータを投入することを前提にしたツールを、 大量データにそのまま使おうとしていたためです。

しかも、 この数字は本格的に性能テストをするまで 問題として認識されていませんでした。

「これ、普通にやったら終わらないな」

ここから、 移行ツールそのものを見直すことになりました。

ゴールが見えないまま調査を始める

今振り返ると、 この時点で明確な設計書があったわけでも、 完成形が決まっていたわけでもありません。

「2年半をどうにかしなければならない」
それだけが分かっている状態でした。

実際の感覚

まず動かす。

どこが遅いのか調べる。

直してみる。

もう一度テストする。

別のボトルネックが見つかる。

また直す。

いわゆる 「最初に全部設計してから実装」 という進め方ではありませんでした。

見えないゴールに向かって、 とにかく調べて、試して、測る。

それを繰り返していきました。

Pythonの処理を一つずつ分解する

まず、 移行処理の中で何をしているのかを Pythonのコードから追っていきました。

CSVなどのデータを読み込み、 データを加工し、 GIS側へデータを投入する。

その中で、 どこに時間がかかっているのかを 一つずつ確認していきました。

大量データを扱うため、 データ処理には pandas / DataFrameも利用しました。

import pandas as pd

df = pd.read_csv("data.csv")

重要だったのは、 単純にPythonのコードを速くすることではありません。

「どの処理が時間を使っているのか」を 計測してから手を入れる。

CPUを使えていないなら、使い切る

性能テストをしていく中で、 CPUの使用状況も確認しました。

そこで、 1つの処理を順番に実行するだけでは CPUの能力を十分に使えていないことが分かります。

そこで検討したのが concurrent.futures を使った 並列処理です。

from concurrent.futures import ProcessPoolExecutor

DataFrameなどのデータを処理単位に分割し、 ProcessPoolExecutorを利用して 複数プロセスで処理させます。

イメージ

大量データ

DataFrame

複数の処理単位へ分割

ProcessPoolExecutor

複数CPUで並列処理

もちろん、 CPUを使えば使うほど良いという話ではありません。

CPUだけではなく、 メモリやI/O、 外部サービスへの通信なども含めて 状況を確認する必要があります。

「CPUを使い切る」のではなく、 「使えるリソースをどこまで有効活用できるか」 を見る。

vmstatやtopでインフラ側も見る

Pythonだけを見ていても、 本当のボトルネックは分かりません。

そこで、 Linux側のリソース状況も確認しました。

vmstat 1

1秒ごとのCPU、 メモリ、 I/Oなどの状態を確認します。

また、 topも利用して 実行中プロセスのCPU使用率や メモリ使用量などを確認しました。

top

これによって、

Python 処理そのもの
OS CPU・メモリ・I/O
GIS データ投入側

という複数の視点から 性能を確認するようになりました。

CSVの読み込みもボトルネックになる

大量データを扱う場合、 「計算処理だけ速くすればいい」 というわけではありません。

データを読み込むところも 処理時間に影響します。

そこで、 pandasによるCSV処理についても 高速化の方法を調査しました。

その中で利用・検討したものの一つが PyArrowです。

df = pd.read_csv(
    "data.csv",
    engine="pyarrow"
)

CSVの読み込み部分についても 並列化や高速化の仕組みを利用することで、 全体の処理時間を短縮していきました。

こうして、 「データ読み込み」 「データ加工」 「並列処理」 「GISへの投入」 というように、 処理全体を分けて考えるようになりました。

改修して終わりではない。テストしてまた直す

一番大変だったのは、 一度の改修で終わらなかったことです。

例えば、

実際の進め方

改修

性能テスト

CPU使用率を確認

I/Oを確認

処理時間を比較

ボトルネック発見

再改修

これを何度も繰り返しました。

テストは「最後にやるもの」ではなく、 改修の方向性を決めるための材料になりました。

最終的に「2年半」が「約2週間」になった

そうやって、 データ処理と並列化、 CPUやI/Oの状況確認、 CSV読み込みの高速化などを 一つずつ積み重ねていきました。

性能改善の結果

当初の見込み
約2年半



Pythonによる処理改善
並列処理
CPUリソースの有効活用
データ処理の高速化
性能テスト



約2週間

もちろん、 移行処理だけで環境を占有できる場合の話です。

実際の運用を続けながら移行する場合には、 リソースをすべて移行処理に使うことはできません。

その条件では、 約2か月 での移行完了を見込めるところまで 持っていくことができました。

何が一番大変だったのか

技術的に難しい部分もありました。

pandas、 並列処理、 CPU使用率、 I/O、 GIS、 REST APIなど、 調べることはかなりありました。

ただ、 今振り返って一番大変だったのは 技術そのものではありません。

「正解が分からない状態で進めなければならなかった」

仕様書があって、 詳しい人がいて、 「この処理をこう直せばいい」 と分かっていたわけではありません。

まず動かす。
調べる。
仮説を立てる。
改修する。
テストする。
結果を見る。

そして、 また分からないことが出てくる。

その繰り返しでした。

「計画して進めた」というより、進みながら計画ができていった

この案件をきれいにまとめようとすると、

要件を整理する。

性能要件を定義する。

アーキテクチャを設計する。

実装する。

テストする。

という話にしたくなります。

でも、 実際はそんなにきれいではありませんでした。

そもそも、最初はゴールが見えていませんでした。

「2年半かかる」という結果を見て、 そこからどうすればいいのかを考え始めました。

そして、

現実の開発

とりあえず調べる

とりあえず動かす

問題を見つける

改修する

テストする

また問題を見つける

また直す

そうやって進めているうちに、 少しずつ全体像が見えてきました。

最初から計画があったのではなく、 進みながら「何をすべきか」が見えてきた。

そして気がつけば、 最初には想像もしていなかった 大量データを処理できる移行ツールが 出来上がっていました。

「何か出来ちゃった」の正体

結果だけを見ると、 「Pythonで並列処理を実装して、 大量データを高速に処理した」 という話になります。

でも、 実際にやっていたことはもっと泥臭いものでした。

分からない。

調べる。

試す。

失敗する。

また調べる。

少し速くなる。

まだ遅い。

また直す。

これを繰り返しているうちに、 最初には存在しなかった 「大量データを現実的な時間で移行する仕組み」 が出来上がりました。

たぶん、これが実際の開発の一番リアルなところです。

この案件で経験したこと

この案件では、 GISデータ移行だけではなく、 大量データを扱うための パフォーマンス改善についても 多くの経験を得ることができました。

GIS GISデータ移行
Python pandas / データ処理
並列処理 concurrent.futures / ProcessPoolExecutor
高速化 CPUリソースの有効活用
Linux vmstat / top
性能テスト 計測 → 改修 → 再計測

そして、 この案件で一番大きかったのは 技術そのものよりも、

「分からない状態でも、 調べて、試して、測れば、 少しずつ前に進められる」

という経験だったと思います。

最終的な結果

1件投入を前提とした既存ツール



大量データを投入すると 約2年半かかることが判明



Python・pandasによるデータ処理改善
並列処理によるCPUリソース活用
Linuxによるリソース確認
性能テストと継続的な改修



約2週間
※移行処理にリソースを集中できる場合

運用と並行する場合
約2か月

最初から完成形が見えていたわけではありません。

ただ、 目の前の問題を一つずつ調べて、 実際に動かして、 結果を見て、 また直す。

がむしゃらに進めていたら、 最後にはちゃんと使えるものが出来上がっていた。

そんな案件でした。