何が違うのか? PostGIS と最新版 MySQL の GIS 機能を徹底比較 2015 年 11 月 27 日 PostgreSQL カンファレンス 2015 本資料の掲載場所

Similar documents
GIS を中心に 多彩なデータ処理を PostgreSQL で 国府田諭 Satoshi Koda このスライドは (kenpg myna で検索 )

PowerPoint Presentation

PostgreSQL SQL チューニング入門 ~ Explaining Explain より ~ 2012 年 11 月 30 日 株式会社アシスト 田中健一朗

Microsoft PowerPoint pptx

PowerPoint Presentation

メール全文検索アプリケーション Sylph-Searcher のご紹介 SRA OSS, Inc. 日本支社技術部チーフエンジニア Sylpheed 開発者 山本博之 Copyright 2007 SRA OSS, Inc. Japan All right

eラーニング資料 e ラーニングの制作目標 データベース編 41 ページデータベースの基本となる概要を以下に示す この内容のコースで eラーニングコンテンツを作成予定 データベース管理 コンピュータで行われる基本的なデータに対する処理は 次の 4 種類です 新しいデータを追加する 既存のデータを探索

Oracle Database Connect 2017 JPOUG

Microsoft Word - tutorial3-dbreverse.docx

Chapter Two

VB実用Ⅲ⑩ フリーデータベースⅡ

PowerPoint プレゼンテーション

内容 Visual Studio サーバーエクスプローラで学ぶ SQL とデータベース操作... 1 サーバーエクスプローラ... 4 データ接続... 4 データベース操作のサブメニューコンテキスト... 5 データベースのプロパティ... 6 SQL Server... 6 Microsoft

クエリの作成が楽になるUDF

Chapter Two

Microsoft PowerPoint - db03-5.ppt

Microsoft Word - Android_SQLite講座_画面800×1280

Microsoft PowerPoint - 講義補助資料2017.pptx

リレーショナルデータベース入門 SRA OSS, Inc. 日本支社 Copyright 2008 SRA OSS, Inc. Japan All rights reserved. 1

PostgreSQL カンファレンス 2013 証券取引バックオフィスにおける Oracle から PostgreSQL への マイグレーション SBI ジャパンネクスト証券株式会社 イアン バーウィック

,, create table drop table alter table

PGECons技術ドキュメントテンプレート Ver.3

PostgreSQL 9.4 評価検証報告 SRA OSS, Inc. 日本支社高塚遙 :55 ~ 16:30 PostgreSQL 9.4 最新情報セミナー Copyright 2014 SRA OSS, Inc. Japan All rights reserved. 1

データベースS

復習 (SQL 文 ) 3/6 復習 (SQL 文 ) 4/6 表の作成 CREATE TABLE...; 表の削除 DROP TABLE テーブル名 ; 表内のデータが全て消えてしまう. 表内のデータを得る SELECT 列名 FROM 表名...; 表にデータを挿入する. INSERT INTO

iNFUSE インフューズ

スライド 1

スライド 1

PostgreSQL 9.3パーティションの効果検証

名古屋大学 COI 高精度地図フォーマット地図の使い方 文書の概要 2017 年 9 月 6 日版 この文書は, 名古屋大学 COI 高精度地図フォーマットの地図情報を RDBMS に格納し, 検索に利用するための手順を解説したものです. 本来であれば, 地図情報と動的情報は, ともにダイナミックマ

10th Developer Camp - B5

1.SqlCtl クラスリファレンス SqlCtl クラスのリファレンスを以下に示します メソッドの実行中にエラーが発生した場合は標準エラー出力にメッセージを出力します (1)Connect() メソッド データベースへ connect 要求を行います boolean Connect(String

MxLogonサーバサイドツールキット用UI

Sequel のすすめ 私が SQL を嫌いな理由 とみたまさひろ RubyHiroba Sequel のすすめ - 私が SQL を嫌いな理由 Powered by Rabbit 2.0.7

はじめに コースの概要と目的 Oracle をより効率的に使用するための SQL のチューニング方法について説明します また 索引の有無 SQL の 記述方法がパフォーマンスにどのように影響するのかを実習を通して理解します 受講対象者 アプリケーション開発者 / データベース管理者の方 前提条件 S

DPCデータ分析環境をSQL SERVER® 2012 EXPRESS & Access®で構築する

Postgres Plus Advanced Server 9.3パーティションテーブルの特徴と性能検証レポート

Exam : J Title : Querying Microsoft SQL Server 2012 Version : DEMO 1 / 10

Microsoft PowerPoint - 第5章補足-DB2組み込みSQL.ppt

mySQLの利用

このドキュメントに記載されている情報 (URL 等のインターネット Web サイトに関する情報を含む ) は 将来予告なしに変更することがあります このドキュメントに記載された内容は情報提供のみを目的としており 明示または黙示に関わらず これらの情報についてマイクロソフトはいかなる責任も負わないもの

Exam : 1z0-882 日本語 (JPN) Title : Oracle Certified Professional, MySQL 5.6 Developer Vendor : Oracle Version : DEMO 1 / 4 Get Latest & Valid 1z0-882-JP

データセンターの効率的な資源活用のためのデータ収集・照会システムの設計

結合演算 ( 復習 ) データベース論 (9) R 社員番号 氏名麻生太郎安部晋三与謝野馨森喜朗 部門経理課営業課総務課営業課 S 部門経理課営業課総務課 電話 問合せ言語と SQL(2) R S 社員番号

データ構造

HeartCoreインストールマニュアル

テクニカルドキュメントのテンプレート

SOC Report

<4D F736F F D208D C8FEE95F18DEC90AC A B D836A B2E646F63>

標準化 補足資料

PA4

Taro php.jtdc

1,.,,,., RDBM, SQL. OSS,, SQL,,.

第 5 章 結合 結合のパフォーマンスに影響を与える結合の種類と 表の結合順序について内部動作を交えて 説明します 1. 結合処理のチューニング概要 2. 結合の種類 3. 結合順序 4. 結合処理のチューニングポイント 5. 結合関連のヒント

Microsoft Word - SQL.rtf

n n n ( ) n Oracle 16 PostgreSQL 3 MySQL

Caché SQL に関するよくある質問

オープンソースデータベース PostgreSQL 最新動向のご紹介

ツール 開 発 の 目 的 2 1 PostgreSQL / PostGIS データをシームレスに 可 視 化 したい 2 R との 連 携 作 業 のプラットフォームを 作 りたい

第 2 章 PL/SQL の基本記述 この章では PL/SQL プログラムの基本的な記述方法について説明します 1. 宣言部 2. 実行部 3. 例外処理部

第 1 章 条件分岐 この章では 条件に応じて処理を分岐する方法について説明します 1. CASE 式で複雑な条件分岐を実現 2. 関数を使用した条件分岐 3. MERGE 文による条件に応じた DML の実行

CodeGear Developer Camp

目次 1. HLA Fusion 3.0 がインストール可能な環境 HLA Fusion 3.0 のインストール HLA Fusion 3.4 のインストール 初期設定用データベース接続 ( 初めての方のみ ) 既存データベースのUpg

PowerPoint プレゼンテーション

ShikumiBunkakai_2011_10_29

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

PostgreSQL Plus 管理者ガイド

test

tkk0408nari

目次 更新履歴... 1 はじめに... 3 レコードセット?... 3 準備... 5 SQL でデータを取得する... 6 データのループ処理... 7 列の値を取得する... 7 対象行を変更する (MoveFirst, MoveNext, MovePrevious, MoveLast)...

PowerPoint プレゼンテーション

スライド 0

モデリング操作ガイド (データベースモデリング編)

データベースアクセス

Web 環境におけるレイヤー別負荷の 2 違い DB サーバ AP サーバ 後ろのレイヤーほど負荷が高く ボトルネックになりやすい

SQL 基礎 (6) JOIN 句 - データの結合 作成日 : 2016/02/22 作成者 : 西村 更新履歴 更新日 更新概要 作業者 2016/02/22 新規作成 西村 はじめに この資料では 下記のような JOIN によるテーブル ( データ ) の結合について簡単に説明します INNE

Proc luaを初めて使ってみた -SASでの処理を条件に応じて変える- 淺井友紀 ( エイツーヘルスケア株式会社 ) I tried PROC LUA for the first time Tomoki Asai A2 Healthcare Corporation

Basic descriptive statistics

情報システム設計論II ユーザインタフェース(1)

Microsoft Word - no103.docx

Microsoft Word - sample_adv-programming.docx

第 2 章 問合せの基本操作 この章では データベースから情報を検索する際に使用する SELECT コマンド および SELECT コマンドと 同時に使用する句について説明します 1. 問合せとは 2. 基本的な問合せ 3. 列の別名 4. 重複行を一意にする 5. 検索行の絞込み 6. 文字パター

Microsoft Word - index.html

C#の基本

Rational Roseモデルの移行 マニュアル


1 SQL Server SQL Oracle SQL SQL* Plus PL/SQL 2 SQL Server SQL Server SQL Oracle SQL SQL*Plus SQL Server GUI 1-1 osql 1-1 Transact- SQL SELECTFROM 058

目次 演習 0 分析資料を作成する前に... () 利用環境... () データのダウンロード方法... 演習 - Excel による集落の現状把握...4 (0) 成果物のイメージ...4 () 利用するデータと分析指標...4 漁業センサス...4 () データセットの作成...5 (3) 分析

はじめに 面的評価支援システム操作マニュアル ( 別冊 ) 国土地理院数値地図 25000( 空間データ基盤 ) 変換編 は 国土地理院の HP よりダウンロードした数値地図 25000( 空間データ基盤 ) の地図データを 面的評価支援システム 用に変換するツールの使用方法についてまとめたものです

iNFUSE インフューズ

1 ex01.sql ex01.sql ; user_id from (select user_id ;) user_id * select select (3+4)*7, SIN(PI()/2) ; (1) select < > from < > ; :, * user_id user_name

~モバイルを知る~ 日常生活とモバイルコンピューティング

PowerPoint プレゼンテーション

Taro-QGIS 3.2

機械学習 ツール入門

ii II Web Web HTML CSS PHP MySQL Web Web CSS JavaScript Web SQL Web

基本サンプル

スライド 1

Microsoft PowerPoint - exp2-02_intro.ppt [互換モード]

( 目次 ) 1. はじめに 開発環境の準備 仮想ディレクトリーの作成 ASP.NET のWeb アプリケーション開発環境準備 データベースの作成 データベースの追加 テーブルの作成

Transcription:

何が違うのか? PostGIS と最新版 MySQL の GIS 機能を徹底比較 2015 年 11 月 27 日 PostgreSQL カンファレンス 2015 本資料の掲載場所 http://kenpg.bitbucket.org/blog/201511/29.html

本 の内容 1 それぞれの最新版で GeoJSON データを処理しながら 較 対象 : MySQL Community Server 5.7.9 対象 : PostgreSQL 9.5 Beta 2 + PostGIS 2.2.0 使うデータ : MAPZEN の世界の 政界から 本のもの さらに» PostgreSQL 9.5 で便利になった外部テーブルのインポート例» 統計処理 語 Rを組み込むPL/Rの利 例» 時間があれば紹介

語等について 2 GIS : Geographic Information System 地理情報システム 情報の呼び はいろいろあるけど 今 は特に区別しません GISデータ 地理データ 空間データ 位置情報データ etc. MySQL の GIS 機能と毎回 うのは 倒なので 省略する場合があります 処理時間を した箇所は だいたい10 回くらい繰り返して同様の結果になったものから ある1 回を例 してます

最初に PostGIS と MySQL のあらまし 3

PostGIS とは 4 PostgreSQL の拡張機能 GIS のデータ型 関数 若 のテーブルやビューを追加 2001 年 : 最初のバージョン0.1 2005 年 : 1.0.0リリース ( 当時 PostgreSQLは8.0) だいたい1 年おきに 1.1 -> 1.2 -> 1.3 -> 1.4 -> 1.5 2012 年 : 幅に進化したバージョン2.0へ その後もバージョンアップ 2015 年 10 2.2リリース 詳しくは : Introduction to PostGIS 第 1 章 ( 本語 ) http://workshops.boundlessgeo.com/postgis-intro-jp/introduction.html 最新 2.2 開発版のマニュアル 本語訳 http://www.finds.jp/docs/pgisman/2.2.0/index.html

MySQL の Extensions for Spatial Data 5 拡張機能でなく ビルトインされている GIS のデータ型と関数 Extensionsというのは 標準的なSQLやRDBMSに対しての意味 詳しくは : MySQL 5.6 Reference Manual - 空間データの拡張 ( 本語 ) http://dev.mysql.com/doc/refman/5.6/ja/spatial-extensions.html 2004 年 : MySQL 4.1で追加 ( 略 ) 2014 年 : MySQL 5.7.5(GeoJSON 関数など追加 ) 2015 年 : MySQL 5.7.6(2 点の経緯度から距離を出す関数など ) データの内部形式が PostGIS と異なる ダンプファイルでの互換性なし

PostGIS が MySQL への拡張でなかった理由 6 先ほど紹介の いわく Introduction to PostGIS 第 1 章 ( 本語 ) http://workshops.boundlessgeo.com/postgis-intro-jp/introduction.html オープンソースデータベースをよく知る 々からよく聞かれるのが なぜ PostGISをMySQL 上で構築しなかったのか? です (... PostgreSQLの特徴を列挙... ) 総じて PostgreSQLにより 新しい空間型の追加が容易となる開発 程を経ることができると えます (... 中略... ) MySQLが バージョン4.1から基本的な空間型をリリースしたとき PostGIS チームはそのコードを て そしてまた実際に使ってみて 改めてPostgreSQL を使 しようという決意を強めました

最新版ではどうなのか? 実際に使ってみる 7

実 環境 8 ハードウェア ( ストレージ : Crucial M500 SSD) Windows 7 64bit MySQL Community Server 5.7.9 PostgreSQL 9.5 Beta 2 + PostGIS 2.2.0 ともに ZIP 版を使い バッチファイルでサーバ起動 ( サービスでない ) 設定はデフォルトのまま # チューニングしないと使えない では GIS ユーザにとって敷居が すぎ

PostGIS : まずインストールから 9 Linux パッケージ管理システムで楽々 Mac postgres.app なら最初から ってる Windows スタックビルダが使える Windows ただし PostgreSQL がサービスになっている前提らしい 動インストール ファイル http://postgis.net/windows_downloads/

PostGIS : データベース作成と準備 10 create database test_gis with encoding 'UTF8' lc_collate = 'C' lc_ctype = 'C'; create extension postgis; -- この DB に PostGIS を導入 select postgis_full_version(); -- バージョン確認 ------------------------------------------------------------------ POSTGIS="2.2.0 r14208" GEOS="3.5.0-CAPI-1.9.0 r4090" PROJ ="Rel. 4.9.1, 04 March 2015" GDAL="GDAL 2.0.1, released 2 015/09/15" LIBXML="2.7.8" LIBJSON="0.12" RASTER (1 row) select version(); -- 参考まで 本体のバージョン ---------------------------------------------------------------- PostgreSQL 9.5beta2, compiled by Visual C++ build 1800, 64-bit

データ 11 MAPZEN というサイトで配布されている Borders -> Japan https://mapzen.com/data/borders/ OpenStreetMap から 世界各国の 政界を抽出 ただし海岸線はなく 領海までの区域 に拡張されている ファイル : 国別の GeoJSON(Japan 59.2 MB) 世界 括もあり

GeoJSON とは 12 JSON 形式で GIS データを格納するオープンな規格 公式ウェブサイト http://geojson.org/ 仕様 ( 本語 ) http://s.kitazaki.name/docs/geojson-spec-ja.html PostGIS 出 はバージョン 1.5 以降で可 は 2.0 以降 MySQL JSON 体を含め 5.7 で初めて対応

GeoJSON を きな 字列 として読み込む 13 create table borders_raw as select * from unnest(array[4, 7, 10]) as admin_level, format('1127_borders/admin_level_%s.geojson', admin_level) as fname, pg_read_file(fname) as raw; -- 3 rows affected, 6926 ms execution time. データフォルダの下 or シンボリックリンク先にファイルを置き pg_read_file() で つの 字列として読み込む

GeoJSON 1 ずつのテーブルにするクエリ例 14 create table borders_geom as select admin_level, row_number() over(partition by admin_level) as gid, json->'properties' as prop, ST_GeomFromGeoJson(json->>'geometry') as geom -- 地理データ from borders_raw, json_array_elements(raw::json->'features') as json; -- 2050 rows affected, 24133 ms execution time.

以上 2 クエリの振り返り (GeoJSON のテーブル化 ) 15 1. GeoJSON ファイルを pg_read_file() で読める場所に置く 2. ファイル名の列などを付け 1 ファイル 1 字列として 時テーブル化 3. つのGeoJSONは トップ -> 'features' で配列になる その各要素を json_array_elements() で ずつにバラす 各 のJSONから キー propertiesで属性を geometryで地理データを取り出し PostGIS のジオメトリ型に変換 4. キー propertiesにidが ってない場合 ( 今回もそう ) row_number() とかを使って適宜 IDを振る 5. 以上のクエリ結果を CREATE TABLE... AS でテーブル化 SELECT... INTO でもいいと思います

インポート結果の確認 (QGIS) 16 QGIS : オープンソースのデスクトップ型 GIS ソフトの代表格 QGIS : PostGIS をはじめ様々なデータベースに対応 これで今回のテスト テーブルが出来上り

MySQL : PostGIS と違う点 17 1. 拡張機能ではない インストールや DB への設定が不要 2. pg_read_file() に相当する関数がない LOAD DATA コマンドで GeoJSONを 1 1 列のデータ として読み込む load data infile './1127_borders/admin_level_4.geojson' into table borders_raw lines terminated by '\\' (raw); -- Query OK, 1 row affected (16.43 sec) GeoJSON の列 (raw) 以外は 別途 UPDATE クエリで追加

MySQL : PostGIS と違う点 ( 続 ) 18 3. PostGIS と同名の関数 ST_GeomFromGeoJSON() で丸ごと読める alter table borders_raw add geom GEOMETRY; update borders_raw set geom = ST_GeomFromGeoJson(raw) where admin_level = 4; -- Query OK, 1 row affected (1 min 24.21 sec) 4. 読み込んだGeoJSONデータを MySQL Workbench で確認できる ( バージョン6.2 以降 画 は次 ) 詳しくは : The MySQL Workbench Team Blog - Workbench 6.2: Spatial Data http://mysqlworkbench.org/2014/09/mysql-workbench-6-2-spatial-data/

MySQL Workbench : Spatial View 19

MySQL Workbench : Spatial View 20

MySQL Workbench : Spatial View 21

ただし JSON の処理に難あり 22 create table borders_json (admin_level int, js json); insert borders_json select admin_level, cast(raw as JSON) from borders_raw where admin_level = 4; ERROR 1301 (HY000): Result of json_binary::serialize() was larger than max_allowed_packet (4194304) - truncated 305 KBの さなGeoJSON 字列 JSON 型に変換できたしかし19.0 MBのGeoJSON( 本の都道府県境界 ) 変換できず max_allowed_packet の値を きく設定しても 今回は解決せず JSON にできない 1 ずつの普通のテーブル にできない

仕 ないので PostGIS からダンプして読み込み 23 -- ON PostGIS copy ( select admin_level, gid, prop, ST_AsGeoJson(geom) from borders_geom ) to 'R:/tmp/dump_postgis.tsv'; -- 2050 rows affected, 10093 ms execution time. -- ON MySQL create table borders_geom (admin_level int, gid int, prop JSON, geojson JSON); load data infile './1127_borders/dump_postgis.tsv' into table borders_geom; -- Query OK, 2050 rows affected (27.68 sec) alter table borders_geom add geom GEOMETRY; update borders_geom set geom = ST_GeomFromGeoJson(geojson); -- Query OK, 2050 rows affected (54.74 sec)

ここまでの作業と処理時間 24 読み込み対象 : GeoJSON * 3 ファイル (304 KB, 19.0 MB, 160 MB) PostGIS : ファイル読み込みクエリ 7.0 sec PostGIS : テーブルへの変換クエリ 24 sec PostGIS : ダンプ出 10 sec MySQL : ( 処理内容が違うので 参考まで ) MySQL : ダンプファイル読み込み 28 sec MySQL : GISデータへの変換クエリ 55 sec MySQL GeoJSONを丸ごと読み込めるのは利点しかし 属性を抽出しGISデータと合わせて普通のテーブルにするなら結局 JSONとしてのパース & 操作が必要 PostgreSQL JSONの操作 ( 配列を にばらす等 ) が豊富で便利!

同じテーブルができたので 何か関数を使ってみる 25

地理データどうしの 重なり とかを調べる 26 今回の対象は 政界で囲まれた ( ポリゴン ) ポリゴンどうしの 空間的な関係 を調べられる関数 いろいろ MySQL と PostGIS 両 にあるもの : ST_Contains(), ST_Crosses(), ST_Disjoint(), ST_Equals() ST_Intersects(), ST_Overlaps(), ST_Touches(), ST_Within() PostGIS だけにあるもの : ST_ContainsProperly(), ST_Covers(), ST_CoveredBy() ST_DWithin(), ST_Relate(), 他にも多数 関数だけでなく演算 も多数 &&, &&&, <<, @, 等々 MySQL だけにあるもの : ポリゴンを囲む矩形 (MBR) で判断する関数群

空間的な関係を調べる とは 27 左 : http://www.finds.jp/docs/pgisman/2.2.0/st_contains.html 右 : http://www.finds.jp/docs/pgisman/2.2.0 /using_postgis_dbmanagement.html

何を調べるか : 今回のデータで けている 県 28 select admin_level, count(*) from borders_geom group by admin_level; admin_level count -------------+------- 4 46 <-- 都道府県らしいが 一つ足りない 7 1743 <-- 市町村 10 261 <-- よく分からない (3 rows) 調べる 法 (1) 市町村で どの都道府県とも重ならない ものを検索 つかれば その市町村名から りない県 を推測できる 調べる 法 (2)46 都道府県を つのポリゴンに融合 それと重ならない市町村を検索する つかれば ( 同上 )

法 (1)PostGIS で 29 select cities.prop :: text -- JSON のままだと except 使えないので文字にキャスト from borders_geom as cities where admin_level = 7 -- 全ての市区町村 except all select cities.prop :: text from borders_geom as prefs, borders_geom as cities where prefs.admin_level = 4 and cities.admin_level = 7 and st_intersects(prefs.geom, cities.geom); -- 都道府県と市区町村で 重なる 組を列挙 そして引く 地理データの列 (geom) にインデクス付け explain する ( 次 )

法 (1)PostGIS のクエリプラン 30 QUERY PLAN ----------------------------------------------------------------------- HashSetOp Except All (cost=0.00..566.45 rows=1743 width=32) -> Append (cost=0.00..558.50 rows=3180 width=32) -> Subquery Scan on "*SELECT* 1" (cost=0.00..155.77 rows=1743 wid -> Seq Scan on borders_geom cities (cost=0.00..138.34 rows=17 Filter: (admin_level = 7) -> Subquery Scan on "*SELECT* 2" (cost=0.14..402.73 rows=1437 wid -> Nested Loop (cost=0.14..388.36 rows=1437 width=32) -> Seq Scan on borders_geom prefs (cost=0.00..129.63 rows Filter: (admin_level = 4) -> Index Scan using borders_geom_geom_idx on borders_geom Index Cond: (prefs.geom && geom) Filter: ((admin_level = 7) AND _st_intersects(prefs.g (12 rows) 地理データのインデクスが使われる 結果は次

法 (1)PostGIS での結果 31 約 4 秒で結果取得 ( 島根県がなかった )

法 (1)MySQL で 同様のクエリ 32 select x.prop from borders_geom as x where admin_level = 7 and not exists ( select cities.prop from borders_geom as prefs, borders_geom as cities where prefs.admin_level = 4 and cities.admin_level = 7 and st_intersects(prefs.geom, cities.geom) ); and x.prop = cities.prop -- PostgreSQL では文字型にキャストして比較» EXCEPT 句を使えないので NOT EXISTS で代» PostGIS で実 したら 先ほどと同様の結果» MySQL では JSON 型をそのまま = 演算 で 較できる

法 (1)MySQL のクエリプラン ( 抜粋 ) と実 結果 33 explain ( 前頁のクエリ ) table partitions type possible_keys key key_len ref ro -------+------------+------+---------------+------+---------+------+--- x NULL ALL NULL NULL NULL NULL 20 cities NULL ALL geom NULL NULL NULL 20 prefs NULL ALL geom NULL NULL NULL 20» 地理データのインデクスは 候補 になるが使われない 所要 44 秒

法 (2) 都道府県を融合 PostGIS の場合 34 -- 都道府県を融合した一つのポリゴンを 別テーブルにする create table union_prefs as select ST_Union(geom) as geom from borders_geom where admin_level = 4; -- one row affected, 15273 ms execution time. -- 検索 select cities.prop from borders_geom as cities, union_prefs as prefs where cities.admin_level = 7 and not ST_intersects(cities.geom, prefs.geom); フルスキャンになったが 約 0.8 秒

結果を QGIS で確認 35

法 (2)MySQL では厳しい その理由 36 複数ポリゴンを 括して融合する 集約関数 がない mysql> create table union_prefs as -> select ST_Union(geom) as geom -> from borders_geom -> where admin_level = 4; ERROR 1582 (42000): Incorrect parameter count in the call to native function 'ST_Union' 関数 ST_Union() は 2つの地理データを融合するのみ例えば ST_Union( 東京都, 埼 県 ) のように 数値で えば 2 つの数の加算はできても sum がない 状態 ストアドを書けば可能かもしれないが

融合 (Union) に限らず MySQL には 地理データの集約関数 がない 37 地理データを RDBMS で扱うメリットが半減してしまう PostGIS の集約関数 (ST_Union 以外 ) :» ST_Accum() 配列型での array_agg に当たるもの» ST_Collect() 融合ではなく 集合 を返す ( 境界線を残す )» ST_Extent() 全体を囲む矩形を返す» ST_Polygonize() など 実質的な集約関数 ( 複数の地理データ つのデータに変換 ) :» ST_LineMerge() 線分を 本につなげる ( 経路探索で重宝 )» ST_BuildArea() など多数

その他 MySQL の主な制約 38 経緯度データ メートル座標系へ変換できないだから 経緯度データに対して 線の さ や 積 を出せない ( 計算はできるが 度から求めた無意味な値になる ) ただし 2 点間の距離だけは バージョン5.7.6から可能 地球が 球 でなく 回転楕円体 であることは考慮外地球は 南北に少しつぶれた 形をしている ( 道上の1 点から 東へ90 度 った距離 > 北へ90 度 った距離 ) PostGISでは どちらも選べる 計算の速い 球 PostGISでは どちらも選 遅いけど実際に近い 回転楕円体 般的な GIS データ (Shapefile) のインポートツールが付属していない

両 で 較できるもの : knn 検索 (k 最近傍検索 ) 39

knn 検索 (k 最近傍検索 ) とは 40 NN : Nearest Neighbour( 最近傍 ) の略 ある点から 個数 k の NN を探す knn 例 : 今いる場所から 近い順に ATM を 10 ヶ所ピックアップしたい SQL 体は単純 ( 下の関数名は仮 ) select atm from tb_atms -- 検索対象テーブル order by distance(atm, point(139, 35)) -- 今いる場所 limit 10; -- k = 10 問題 : 検索対象が膨 な場合の実 コスト 上記クエリだと 1 検索対象の全 につき 今いる場所との距離を算出上記クエリだと 2 距離の短い順にソートし 先頭 10 件を取り出す

従来の 般的な改善策 41 全 につき距離を出さず ある範囲の に絞ってから距離を測る select atm from ( select atm from tb_atms where intesects(atm, box(138, 34, 140, 36)) -- 検索対象を絞り込むサブクエリ box は適当に決める -- 上の関数名は仮 ) foo order by distance(atm, point(139, 35)) -- 今いる場所 limit 10; -- k = 10 上記サブクエリでインデクスを有効にすれば 速い 問題 : 適切な絞り込み範囲は どうやって決めればよいのか

PostgreSQL 9.5 + PostGIS 2.2 はもっと簡単 42 演算 <-> で 事前の絞り込みなく 速に knn 検索できる select atm from tb_atms order by atm <-> 'POINT(138 35)' :: geography limit 10; テスト に約 63 万の点を作成 ( 都道府県ポリゴンの周縁の構成点 ) create table fringes as select prop->>'name' as pname, (st_dumppoints(geom)).geom from borders_geom where admin_level = 4; -- 629456 rows affected, 6599 ms execution time.

最初の単純な SQL だと 43 select pname from fringes -- 検索対象テーブル order by st_distance_sphere(geom, 'SRID=4326; POINT(138 35)':: geometry) limit 10; 全 63 万 に対して メートル単位の距離を算出するので遅い (46 秒 )

経緯度からメートル距離を出しやすくするため 検索対象の点を geography 型で準備 44 alter table fringes add geog geography; update fringes set geog = geom::geography; -- 629456 rows affected, 3525 ms execution time. -- インデクス付加 create index on fringes using gist (geog); -- Query returned successfully with no result in 6786 ms. 準備はこれだけ 約 10 秒 クエリの explain analyze 結果 : 次

演算 <-> を使うとインデクスが有効になる 45 select pname, st_distance( 'POINT(138 35)' :: geography, geog) as dist from fringes order by geog <-> 'POINT(138 35)' :: geography limit 10; 46399 ms 5 ms 信じられないくらい速い! クエリ 体の結果 : 次

演算 <-> を使ったクエリ結果 46 select pname, st_distance( 'POINT(138 35)' :: geography, geog) as dist from fringes order by geog <-> 'POINT(138 35)' :: geography limit 10; knn 検索は地球を 球 として い 最近傍 10 件への距離 ( 列 dist) はより正確な 回転楕円体 で算出 演算 <-> は以前からあったが 距離の精度が低かった それが最新 PostGIS 2.2で改善された http://postgis.net/docs/manual-2.2/geometry_distance_knn.html

MySQL での knn 検索 ( 準備 ) 47 テスト 63 万の点テーブルを作成 PostGIS のように ポリゴンを構成する全点を 括抽出 はできない create table centroids as select st_centroid(geom) as geom from borders_geom; set @n := 0; -- 以下を繰り返し 点の数が約 63 万個になるまで set @n := @n + 1; insert into centroids select ST_PointN( ST_ExteriorRing( ST_GeometryN(geom, 1)), @n) from borders_geom where ST_NumPoints( ST_ExteriorRing( ST_GeometryN(geom, 1))) >= @n; select count(*) from centroids;

MySQL での knn 検索 ( 続 ) 48 対象テーブルの 数と explain の抜粋 ( インデクスは使われない ) select count(*) from centroids; -- 対象の点テーブルの行数 +----------+ count(*) +----------+ 630123 +----------+ explain select ST_AsText(geom) from centroids order by st_distance_sphere(geom, ST_GeomFromText('POINT(138 35)', 4326)) limit 10; table partitions type possible_keys key key_len r ----------+------------+------+---------------+------+---------+-- centroids NULL ALL NULL NULL NULL N

MySQL での knn 検索 ( 結構速い ) 49 select ST_AsText(geom) from centroids order by st_distance_sphere(geom, ST_GeomFromText('POINT(138 35)', 4326)) limit 10; +-----------------------------+ ST_AsText(geom) +-----------------------------+ POINT(138.044186 34.923237) POINT(138.044175 34.92313) POINT(138.044118 34.923002) 最初の単純なクエリで POINT(138.044084 34.922856) 1 秒余りと結構速い POINT(138.044055 34.922699) 同じクエリでPostGISは POINT(138.044031 34.922631) POINT(138.043952 34.922403) 40 数秒かかった POINT(138.043864 34.922192) POINT(138.04378 34.922065) POINT(138.043666 34.921936) 特段の準備やチューニング +-----------------------------+ せずこの性能なので knn 10 rows in set (1.31 sec) 検索には合っているかも

PostgreSQL の FDW( 外部データラッパ ) と PostGIS 50

例 : 外部の PostGIS データに 必要な時だけアクセス 51 必要なもの postgres_fdw( 標準的な拡張機能の つ ) 必要なもの 外部で稼動している PostGIS サーバ PostGIS を開発したRefractions Research 社が 同社のオープンソース GIS udig のチュートリアル にPostGIS サーバを公開 http://udig.refractions.net/files/docs/latest/user/getting_started /walkthrough1/postgis.html このチュートリアル テーブルを postgres_fdw で外部テーブル化 その際 Postgres 9.5 新機能 import foreign schema がとても便利 外部テーブルをマテリアライズドビューにして 必要時だけアクセス

udig チュートリアル サーバに接続テスト 52

外部テーブル作成 53 CREATE EXTENSION postgres_fdw; CREATE SERVER udig FOREIGN DATA WRAPPER postgres_fdw OPTIONS (host 'www.refractions.net', port '5432', dbname 'demo-bc'); CREATE USER MAPPING FOR postgres SERVER udig OPTIONS (user '****', password '****'); IMPORT FOREIGN SCHEMA public LIMIT TO ( bc_border, bc_hospitals, bc_municipality, bc_pubs, bc_voting_areas ) FROM SERVER udig INTO public; -- Query returned successfully with no result in 3806 ms.

外部テーブルができたことの確認 54

外部テーブルをマテビューとしてコピー 55 create materialized view myviews.bc_voting_areas as select * from public.bc_voting_areas; -- 7986 rows affected, 55490 ms execution time. -- インターネット経由でデータ取得するので時間かかるが この 1 回のみ -- 他のテーブルも 必要なら同様に 左 : 外部テーブルから取得 (5428 ms), 右 : マテビューから (16 ms)

PL/R( 統計処理 語 R の組み込み ) と PostGIS 56

例 : RのGIS パッケージの つ spatstat に PostGIS データを投 して分析するテンプレを作る 57 必要なもの R http://www.r-project.org/ 必要なもの PL/R http://www.joeconway.com/plr/ 必要なもの まだ Win + Postgres 9.5 がないので 9.4 を使 spatstat と若 の R のパッケージが必要だが R 上で簡単に れられる 主な流れ テンプレとなる 作ストアドを作成 ( 語に plr と指定 ) 主な流れ ストアド内で DB の PostGIS データを R へ読み込む 主な流れ 後は 普通の R スクリプトと同様にストアド内で処理を書く spatstat で 点分布 カーネル密度推定 を実 結果をファイル出

出来上がり後の実 例 58 select myfunc.poi_dens( -- ジオメトリを集約し メートル座標系に変換してストアドに渡す st_astext(st_transform(st_setsrid(geom, 4326), 3095)), 30, 'R:/test.svg', jname) from ( select st_collect(geom) as geom, text ' 東京 23 区 ' as jname from borders_geom where prop->>'name' like '% 区 %' ) foo;

出来上がり後の実 例 59 select myfunc.poi_dens( -- ジオメトリを集約し メートル座標系に変換してストアドに渡す st_astext(st_transform(st_setsrid(geom, 4326), 3095)), 30, 'R:/test.svg', jname) from ( select st_collect(geom) as geom, text ' 東京 23 区 ' as jname from borders_geom where prop->>'name' like '% 区 %' ) foo;

select r_version(); -- これが R のバージョン ( 準備 OK) ------------- (platform,i386-w64-mingw32) (arch,i386) (os,mingw32) (system,"i386, mingw32") (status,"") (major,3) (minor,2.2) (year,2015) PostgreSQL 9.4 で PostGIS, PL/R を準備 60 create extension postgis; create extension plr; select postgis_full_version(); ------------- POSTGIS="2.1.5 r13152" GEOS="3.4.2-CAPI-1.8.2 r3922" PROJ="Rel. 4 select plr_version(); ------------- 08.03.00.16

PL/R で使うパッケージを R 本体上でインストール 61 install.packages(rgeos) # PostGIS の地理データ ( のテキスト出力 ) を R に読み込む # 具体的には readwkt() 関数を使用 install.packages(sp) # R の地理データクラスの基本 install.packages(spatstat) # 空間的な点分布への分析等ができる PostgreSQLサーバ起動中にインストールした場合 もしかしたら サーバ再起動が必要かも

好きな場所にストアドを作り R 語で書く 62 create or replace function myfunc.poi_dens (wkt text, num int, svg text, jname text) # 数値, 文字など一般的なデータ型は そのまま引数で渡せる # 引数名も付けられる # wkt : PostGIS データを ST_AsText() で文字にして渡す # num : 今回ポリゴン内にランダムに点を打つ その数 # svg : 結果を SVG で出力する そのパス # jname : SVG の中に書き込む 処理対象のラベル returns void language plr immutable as $R$ library(rgeos) library(sp) library(spatstat) # インストールしたパッケージを読み込む

好きな場所にストアドを作り R 語で書く ( 続 ) 63 ( つづき ) g1 = readwkt(wkt) # PostGIS データ R の地理データクラス bb = g1@bbox p1 = spsample(g1, n=num, type='random') # ランダムな点 xy = p1@coords pp = ppp(xy[,1], xy[,2], bb[1,], bb[2,], c('unit', 'unit')) dense = density(pp) # ppp spatstat パッケージで分析する際の一つの基本クラス # point pattern dataset in the two-dimensional plane # density() カーネル密度推定の関数 ( つづく 後はプロットして SVG 出力するだけ )

好きな場所にストアドを作り R 語で書く ( 続 ) 64 ( つづき ) colors = colorramppalette(c('white', 'orange')); # 色は適当 svg(file=svg) plot(dense, main='', xlim=bb[1,], ylim=bb[2,], col=colors) contour(add=t, dense, lty=2) plot(add=t, g1, lwd=2) points(p1, pch=21, bg='red') mtext(cex=2, side=3, family='japan1', text=jname) graphics.off() $R$; このストアドの基本的な使い : select myfunc.poi_dens( ST_AsText( 地理データ ), 20, 'R:/test.svg', ' ラベル ');

好きな場所にストアドを作り R 語で書く ( 続 ) 65 ( つづき ) colors = colorramppalette(c('white', 'orange')); # 色は適当 svg(file=svg) plot(dense, main='', xlim=bb[1,], ylim=bb[2,], col=colors) contour(add=t, dense, lty=2) plot(add=t, g1, lwd=2) points(p1, pch=21, bg='red') mtext(cex=2, side=3, family='japan1', text=jname) graphics.off() $R$; このストアドの基本的な使い : select myfunc.poi_dens( ST_AsText( 地理データ ), 20, 'R:/test.svg', ' ラベル ');

まとめ 66 1. MySQL ピンポイントで 重要な所に注 している感 knn 検索 GeoJSON 対応 Workbench でのGISデータビュー ( 正直うらやましい ) 2. PostGIS 豊富な集約関数 グループ的なデータを作る / ばらす等 RDBMS ならではのメリットは圧倒的 3. PostGIS 2.2 今回は割愛したけど Temporal Spatial Analysis : 時空間分析 の関数が初めて追加されたり さらに進化 4. PostGISの泣き所? 簡単なビュワーがない / 機能 情報が多すぎてよく分からない / チュートリアル データが少ない # 今後オープンソースの GIS-DB が発展することを期待してます #