前提・実現したいこと
MySQL8.0を利用し、下記のテーブルPolyがあります。なお、そのレコード数は約24万です。
MySQL
1# Input table 2CREATE TABLE IF NOT EXISTS Poly ( 3 id INTEGER AUTO_INCREMENT, 4 prop int(11),#各ポリゴンの属性 5 geom POLYGON NOT NULL, 6 PRIMARY KEY (id), 7 SPATIAL KEY `geom`(geom)); 8# Output table 9CREATE TABLE IF NOT EXISTS child_parent ( 10 child INTEGER NOT NULL, 11 parent INTEGER NOT NULL, 12 geom_c POLYGON NOT NULL,# child のgeom 13 PRIMARY KEY (child ,parent), 14 SPATIAL KEY `geom_c`(geom_c));
実現したいことは、このテーブルから、ポリゴン属性が互いに同じで且つ隣接しているポリゴンの組み合わせを新たなテーブルchild_parentとして出力することです。
最終的な目的は、ポリゴン属性が互いに同じで且つ隣接しているポリゴンを一つのポリゴンにまとめたテーブルを作ることですが、まず、この段階で時間がかかることを解決したいのです。
発生している問題・エラーメッセージ
問題は、レコード数が大きいので、実行時間が多大(40時間でlost connection)にかかることです。
希望は、数時間で終わることを期待しています。
該当のソースコード
最初に実行したSQLです。(40時間でlost connection)
なお、TEMPORARYテーブルは一つのSQLの中で、2回以上は呼び出すことができないというので、Polyとまったく同じものを二つ(Poly_a、Poly_b)用意し、その二つをjoinしています。
MySQL
1INSERT INTO child_parent(child,parent,geom_c) 2select w.id,w.parent,w.geom from 3(SELECT 4 a.id as id, 5 b.id as parent, 6 a.geom as geom 7from Poly_a as a 8join Poly_b as b 9WHERE 10 a.id > b.id and # 自分同士と同じ組み合わせは重複するので不要 11 a.prop = b.prop and # ポリゴンの属性が同じものだけ 12 ST_GeometryType(ST_UNION(a.geom,b.geom)) = 'POLYGON' # 隣接するものだけ 13) as w 14group by w.id;#最終的な目的を考えて、w.idでまとめる。 15
試したこと
時間がかかるので、explainでキーがどのように有効になっているかを以下の通り、確認しました。
MySQL
1explain 2select w.id,w.parent,w.geom from 3(SELECT 4 a.id as id, 5 b.id as parent, 6 a.geom as geom 7from Poly_a as a 8join Poly_b as b 9WHERE 10 a.id > b.id and 11 a.prop = b.prop and 12 ST_GeometryType(ST_UNION(a.geom,b.geom)) = 'POLYGON' 13) as w 14group by w.id; 15 16| id| select_type| table| partitions| type| possible_keys| key| key_len| ref| rows| filtered| Extra| 17|'1'| 'SIMPLE'| 'b'| NULL| 'ALL'| 'PRIMARY'| NULL| NULL| NULL| '248008'| '100.00'| 'Using temporary'| 18|'1'| 'SIMPLE'| 'a'| NULL| 'ALL'| 'PRIMARY,geom_a'| NULL| NULL| NULL| '248097'| '0.33'| 'Using where; Using join buffer (Block Nested Loop)'| 19
結果を見ると、テーブルaのpossible_keysは'PRIMARY,geom_a'となっており、PKとSpatialkeyとが含まれています。しかし、テーブルbのpossible_keysにはが含まれていません。filteredも100になっていて、全てが対象になっている模様です。
なお、テーブルaとテーブルbには、それぞれSPATIAL KEYgeom_a
,geom_b
を設定しています。
そこで、USE INDEX (PRIMARY,geom_a)、USE INDEX (PRIMARY,geom_b)を使ってみましたが、結果は同じでした。
下記のように、FORCE INDEX()を使ったところ、少し結果が異なりましたが、恐らく時間短縮は見込めないと思われます。
MySQL
1explain 2select w.id,w.parent,w.geom from 3(SELECT 4 a.id as id, 5 b.id as parent, 6 a.geom as geom 7from Poly_a as a FORCE INDEX (PRIMARY,geom_a) 8join Poly_b as b FORCE INDEX (PRIMARY,geom_b) 9WHERE 10 a.id > b.id and 11 a.prop = b.prop and 12 ST_GeometryType(ST_UNION(a.geom,b.geom)) = 'POLYGON' 13) as w 14group by w.id; 15 16| id| select_type| table| partitions| type| possible_keys| key| key_len| ref| rows| filtered| Extra| 17|'1'| 'SIMPLE'| 'a'| NULL| 'ALL'| 'PRIMARY,geom_a'| 'PRIMARY'|4| NULL| '248097'| '100.00'| NULL| 18|'1'| 'SIMPLE'| 'b'| NULL| 'ALL'| 'PRIMARY'| NULL| NULL| NULL| '248008'| '0.33'| 'Range checked for each record (index map: 0x1)'| 19
補足情報
MySQLのバージョン:GPL 8.0.12
OS:Windows 7 Professional 64bit
RAM:8.0GB