shapefileをMySQLに取り込む!shp2sqlの紹介

この日記は、RDBMS-GIS(MySQL,PostgreSQLなど) Advent Calendar 2020 の7日目ぶん(あいていたので後から埋めてます)の記事です。

この日記は

 世の中の地理情報データ(位置の情報を含んだデータ)には、shapefile というファイル形式で公開されているものが非常にたくさんあります。この日記では、shapefileのデータをMySQL に取り込む方法として、私が開発している shp2sql というツールを紹介します。

shp2sql の入手

 shp2sql は単一の Python スクリプトです。github にて公開しています。以下のURLから shp2sql.py を取得してください。pythonの動作環境が必要です。
github.com

サンプルデータの入手

 ここでは、国土交通省が公開している「国土数値情報」を利用します。日本の国土に関する様々なデータが公開されていますが、ここでは以下のURLから、「2.政策区域」-「行政地域」-「行政区域(ポリゴン)」と辿ったページより、千葉・令和2年(N03-20200101_12_GML.zip)を取得して説明を続けます。ダウンロードしたzipファイルを展開しておきます。

https://nlftp.mlit.go.jp/ksj/index.html

MySQL側の用意

 MySQL側に、shapefileを取り込むためのデータベース(スキーマ)を作成しておきます。既存のスキーマにデータを取り込みたい場合は、作成不要です。 また、取り込み先のテーブルは作成しておく必要はありません。

CREATE DATABASE shptest;

shp2sql の実行

 展開した(ここでは千葉県の)shapefile があるフォルダに移動します。話をシンプルにするために ここでは、shp2sql.py も同じフォルダに存在していることにします。
 ここで使うshapefileは、拡張子が shp のものの他に、dbf, shx の計3つが必要になります。


 引数なしで shp2sql を実行すると、usage が表示されます。このへんのオプションは、まだまだ今後変更される可能性があります。-h を付けるともう少し詳細に表示されます。

D:\work\> shp2sql.py
usage: shp2sql.py [-h] [-c CHARSET] [-s SRID] [-d] [-x] [-T TABLENAME] input_filename
shp2sql.py: error: the following arguments are required: input_filename


 shapefileMySQLに取り込むには、基本的には、取り込みたい shapefile 名を指定して実行すれば良いのですが、文字コードutf-8 以外の場合は、その文字コードを教えてあげる必要があります。上記ダウンロードした ファイル群は cp932 ですので、-c オプションで与えてあげます。shp2sql は、shapefile を読み込んでSQL文を吐いてくれるだけのツールなので、その結果を mysqlクライアントに渡します。
 先ほどダウンロードした千葉県データの場合(N03-20_12_200101.shp)を取り込む実行例です。

D:\work\>shp2sql.py N03-20_12_200101.shx -ccp932 | mysql -uroot -p shptest


これだけで、shptest データベース内に N03-20_12_200101 テーブルが作られ、メタデータ並びに位置情報データが登録されます。

MySQL Workbench で確認

MySQL Workbench で、全件を見てみるとこんな感じ。SHAPE列に「BLOB」型のデータが入っていることがわかります。

f:id:sakaik:20201220223458p:plain


ひとつの行を選択して、右側から「Form Editor」を選ぶと、こんなふうに1行のデータが表示され、GEOMETRY系のカラムについては、その形も表示されます。
f:id:sakaik:20201220223705p:plain

右側から「Spatial View」で、千葉県全域のデータが入っていることも確認できます。
f:id:sakaik:20201220223410p:plain

もちろん、SELECT文にWHERE句を付けて、自分の見たいデータだけを抽出して確認もできます。みなさんは基本的な教養として我孫子市のコードが 12222 ということは知っていると思うので、それで検索してみた結果です。
f:id:sakaik:20201220223944p:plain
 ほら、我孫子市の形をしているでしょう。 (大丈夫、地元民でも、利根川手賀沼が描かれていないと「このへんこんな形をしていたかなぁ」とか迷ったりしますのでw)

制限事項とか今後の予定とか

 shp2sql.py は、現在開発途上です。まずは動作するものをと目指している段階です。以下の制限事項ならびに、改善を予定しています。

  • 一部のデータ型には未対応:POLYGON/LINESTRING/POINT のような基本的なデータ型には対応していますが、まだ全てのデータ型には対応していません。未対応のデータフォーマットファイルを見つけたら、ぜひお知らせください。調査します。
  • 遅いです:そんなに大きなデータも扱わないので、、と考えていたのですが、(千葉県だけでなく)全国のデータを一括で取り込もうとしていつまでも終わらず苦労しました。相当遅いです。single transaction 化や、INS/UPD ではなく一発のINSERTで実行するようにする等、改善予定です。

おわりに

 一度動く環境を作ってしまえば気楽に shapefileMySQL に取り込むことができる shp2sql.py。ぜひお手元に環境を作成して、試してみてください。取り込みができなかった(エラーとなった)ファイルがありましたら、そのファイルの入手方法とともにお知らせください。特に未対応ファイルトーマットについては優先順位を少しあげて対応を考えたいと思います。(全体としての優先順位は、「まず、ありとあらゆるshapefileMySQLに取り込めるようにすること」それから「速度改善」「便利機能」「きめ細かなエラー処理」です)


2020/12/21追記

 滅茶苦茶処理が遅かった話について。 上記全国のファイルのデータ登録を試みたら、半日以上経っても終わらなかったのですが、原因判明&手元では改善済み。
 解析の都合で、現在のツールでは、INSERT & UPDATE の処理を行っています。この 大量のUPDATEをする際の対象テーブルに、インデックス(プライマリキー)が張られていないというオチでした。PK張ったら、数秒で終わるようになりました。なんだ、色々改良点を考えたけど、その辺りは今のままでもいいのかもしれない(笑)。