このトピックでは、車両のインターネット (IoV) の軌跡クエリシナリオを例として、Lindorm GanosBase SQL を使用して、収集された軌跡ポイントを Lindorm ワイドテーブルに書き込み、時空間範囲に基づいてデータに対して高速なクエリを実行する方法について説明します。
前提条件
LindormTable が有効化されており、データベースエンジンのバージョンが 2.6.5 以降であること。 バージョンの確認またはアップグレード方法の詳細については、「LindormTable バージョンガイド」および「マイナーバージョンの更新」をご参照ください。
JDK 1.8 以降のバージョンがインストールされた Java 環境が必要です。
Lindorm ワイドテーブル SQL の接続アドレスが取得され、ホワイトリストが設定されていること。 詳細については、「インスタンスへのアクセス」をご参照ください。
操作手順
時空間データテーブルを作成し、時空間範囲で軌跡をクエリするには、次のステップを実行します。
時空間データテーブルの作成とデータ書き込み
Lindorm-cli を使用した LindormTable への接続とデータ書き込み
LindormTable に接続します。 この例では、Lindorm-cli を使用して Linux にデプロイされたクライアントから接続します。
JDBC 接続の使用方法の詳細については、「Lindorm ワイドテーブル SQL Java API を使用した LindormTable への接続と使用」をご参照ください。
Lindorm-cli パッケージを解凍します。
接続アドレスを取得し、次のコマンドを実行して Lindorm ワイドテーブルに接続します。
./lindorm-cli -url <jdbc url> -username <username> -password <password>パラメーター
値の例
取得方法
jdbc url
jdbc:lindorm:table:url=http://ld-bp17j28j2y7pm****-proxy-lindorm-pub.lindorm.rds.aliyuncs.com:30060
Lindorm ワイドテーブル SQL の接続アドレス。 取得方法の詳細については、「インスタンスへのアクセス」をご参照ください。
username
root
ユーザー名は Lindorm クラスター管理システムで確認できます。 パスワードを忘れた場合は、クラスター管理システムで変更できます。 詳細については、「ユーザーパスワードの変更」をご参照ください。
password
root
次の結果が返されます。
Connected to jdbc:lindorm:table:url=http://ld-bp17j28j2y7pm****-proxy-lindorm-pub.lindorm.rds.aliyuncs.com:30060 lindorm-cli version: 1.0.15
次の 2 つの方法のいずれかで時空間データテーブルを作成します。
時空間データテーブルは軌跡ポイントを格納します。 軌跡ポイントには、経度 (x)、緯度 (y)、時間 (t) の情報が含まれます。 Lindorm GanosBase では、x と y のデータを 2 つの方法で格納できます。 次の表では、格納方法とその特徴について説明します。
ストレージメソッド
特徴
Geometry(Point)空間データ型を使用して、x と y のデータを単一の列に格納します。高いパフォーマンス。
通常の点座標を使用して、x と y のデータを別々の列に格納します。
既存データを x と y の 2 つの別々の列に格納すると、パフォーマンスが低下します。
Geometry(Point)空間データ型を使用して、x と y のデータを単一の列に格納します。 時空間データテーブルを作成する文は次のとおりです。CREATE TABLE gps_data (id int, g geometry(point), t timestamp, ship_name varchar, PRIMARY KEY(id, t));パラメーター
説明
g
空間列。 空間データ型は
Geometry(Point)です。t
時間列。 サポートされているデータの型は Time、Timestamp、または Long です。 Long 型を使用する場合、時間はミリ秒単位の UNIX タイムスタンプとして表されます。
ship_name
名前列。 たとえば、時空間データポイントを生成する船の名前です。
PRIMARY KEY(id, t)
idとtで構成されるプライマリキー。通常の点座標を使用して、x、y、t のデータを 3 つの別々の列に格納します。 時空間データテーブルを作成する文は次のとおりです。
CREATE TABLE gps_data_point (id int, x double, y double, t timestamp, ship_name varchar, PRIMARY KEY(id, t));
次の 2 つの方法のいずれかで、軌跡ポイントデータを一度に 1 つずつ書き込みます。
ST_MakePoint時空間関数を使用して軌跡ポイントデータを構築します。 たとえば、ST_MakePoint(119.073544,25.3244)は、経度 119.073544、緯度 25.3244 の軌跡ポイントを表します。INSERT INTO gps_data (id, g, t, ship_name) VALUES (1,ST_MakePoint(119.073544,25.3244), '2021-01-01 10:00:00', 'ship001'); INSERT INTO gps_data (id, g, t, ship_name) VALUES (1,ST_MakePoint(119.073544,25.3244), '2021-01-01 10:05:03', 'ship001'); INSERT INTO gps_data (id, g, t, ship_name) VALUES (1,ST_MakePoint(119.073544,25.324382), '2021-01-01 10:08:32', 'ship001'); INSERT INTO gps_data (id, g, t, ship_name) VALUES (1,ST_MakePoint(119.073536,25.324418), '2021-01-01 10:10:22', 'ship001'); INSERT INTO gps_data (id, g, t, ship_name) VALUES (2,ST_MakePoint(19.07352,25.34), '2021-01-01 08:20:21', 'ship002'); INSERT INTO gps_data (id, g, t, ship_name) VALUES (2,ST_MakePoint(19.07352,25.33), '2021-01-01 08:22:20', 'ship002');説明ST_MakePoint時空間関数の詳細については、「ST_MakePoint」をご参照ください。ST_GeomFromText時空間関数を使用して軌跡ポイントデータを構築することもできます。 軌跡ポイントのフォーマットは Well-known Text (WKT) 標準を使用します。 ただし、ST_GeomFromText関数はST_MakePoint関数よりも書き込みパフォーマンスが低くなります。ST_GeomFromText時空間関数の詳細については、「ST_GeomFromText」をご参照ください。
通常の点座標を使用します。
INSERT INTO gps_data_point (id, x, y, t, ship_name) VALUES (1, 119.073544, 25.3244, '2021-01-01 10:00:00', 'ship001'); INSERT INTO gps_data_point (id, x, y, t, ship_name) VALUES (1, 119.073544, 25.3244, '2021-01-01 10:05:03', 'ship001'); INSERT INTO gps_data_point (id, x, y, t, ship_name) VALUES (1, 119.073544, 25.324382, '2021-01-01 10:08:32', 'ship001'); INSERT INTO gps_data_point (id, x, y, t, ship_name) VALUES (1, 119.073536, 25.324418, '2021-01-01 10:10:22', 'ship001'); INSERT INTO gps_data_point (id, x, y, t, ship_name) VALUES (2, 19.07352, 25.34, '2021-01-01 08:20:21', 'ship002'); INSERT INTO gps_data_point (id, x, y, t, ship_name) VALUES (2, 19.07352, 25.33, '2021-01-01 08:22:20', 'ship002');
任意: 次の 2 つの方法のいずれかで、軌跡ポイントデータをバッチで書き込みます。
ST_MakePoint時空間関数を使用します。UPSERT INTO gps_data (id, g, t, ship_name) VALUES(1,ST_MakePoint(119.073544,25.3244), '2021-01-01 10:00:00', 'ship001'),(1,ST_MakePoint(119.073544,25.3244), '2021-01-01 10:05:03', 'ship001'),(1,ST_MakePoint(119.073544,25.324382), '2021-01-01 10:08:32', 'ship001'),(1,ST_MakePoint(119.073536,25.324418), '2021-01-01 10:10:22', 'ship001'),(2,ST_MakePoint(19.07352,25.34), '2021-01-01 08:20:21', 'ship002'),(2,ST_MakePoint(19.07352,25.33), '2021-01-01 08:22:20', 'ship002');通常の点座標を使用します。
UPSERT INTO gps_data_point (id, x, y, t, ship_name) VALUES(1, 119.073544, 25.3244, '2021-01-01 10:00:00', 'ship001'),(1, 119.073544, 25.3244, '2021-01-01 10:05:03', 'ship001'),(1, 119.073544, 25.324382, '2021-01-01 10:08:32', 'ship001'),(1, 119.073536, 25.324418, '2021-01-01 10:10:22', 'ship001'),(2, 19.07352, 25.34, '2021-01-01 08:20:21', 'ship002'),(2, 19.07352, 25.33, '2021-01-01 08:22:20', 'ship002');
SELECT文を使用して、書き込まれたデータをクエリします。ST_AsText時空間関数を使用して、時空間データを人間が判読可能なテキスト形式に変換します。SELECT id, ST_AsText(g) AS position, ship_name FROM gps_data;次の結果が返されます。
+----+------------------------------+-----------+ | id | position | ship_name | +----+------------------------------+-----------+ | 1 | POINT (119.073544 25.3244) | ship001 | | 1 | POINT (119.073544 25.3244) | ship001 | | 1 | POINT (119.073544 25.324382) | ship001 | | 1 | POINT (119.073536 25.324418) | ship001 | | 2 | POINT (19.07352 25.34) | ship002 | | 2 | POINT (19.07352 25.33) | ship002 | +----+------------------------------+-----------+通常の点座標を使用します。
SELECT * FROM gps_data_point;次の結果が返されます。
+----+-------------------------------+------------+-----------+-----------+ | id | t | x | y | ship_name | +----+-------------------------------+------------+-----------+-----------+ | 1 | 2021-01-01 10:00:00 +0000 UTC | 119.073544 | 25.3244 | ship001 | | 1 | 2021-01-01 10:05:03 +0000 UTC | 119.073544 | 25.3244 | ship001 | | 1 | 2021-01-01 10:08:32 +0000 UTC | 119.073544 | 25.324382 | ship001 | | 1 | 2021-01-01 10:10:22 +0000 UTC | 119.073536 | 25.324418 | ship001 | | 2 | 2021-01-01 08:20:21 +0000 UTC | 19.07352 | 25.34 | ship002 | | 2 | 2021-01-01 08:22:20 +0000 UTC | 19.07352 | 25.33 | ship002 | +----+-------------------------------+------------+-----------+-----------+
Java JDBC を使用した LindormTable への接続とデータ書き込み
Lindorm SQL の他のデータの型と同様に、パラメーター化クエリでパラメーターをバインドすることで時空間データを書き込むことができます。 次の Java コードは、Java Database Connectivity (JDBC) の PreparedStatement インターフェイスを使用したパラメーター化クエリで時空間データを書き込む例を示しています。
// 接続を確立します。
Connection connection = DriverManager.getConnection(url, properties);
final String tableName = "testtbl"
// テーブルを作成します。
try (Statement stmt = conn.createStatement()) {
stmt.execute("create table " + tableName +
"(p1 int, c1 varchar, c2 geometry(point), constraint primary key (p1))");
}
// データを書き込むためのパラメーター化クエリ文。
final String upsertSql = "upsert into " + tableName + "(p1,c1,c2) values (?,?,ST_MakePoint(?,?))";
// 文を準備します。
try (PreparedStatement preparedStatement = conn.prepareStatement(upsertSql)) {
// プレースホルダーに対応するパラメーターをバインドします。
preparedStatement.setInt(1, 0);
preparedStatement.setString(2, "name");
preparedStatement.setDouble(3, 5.0);
preparedStatement.setDouble(4, 5.0);
// 書き込み操作を実行します。
preparedStatement.executeUpdate();
}クエリ効率を向上させるための時空間インデックスの作成
クエリ文の WHERE 句に時空間範囲が含まれている場合、時空間インデックスを作成してクエリを高速化できます。 時空間インデックスは、時空間プライマリキーインデックスと時空間セカンダリインデックスに分類されます。 これらは Lindorm のプライマリキーインデックスとセカンダリインデックスに対応します。 詳細については、「時空間インデックスの作成」をご参照ください。
時空間データテーブルのプロパティを設定します。
ALTER TABLE gps_data SET 'MUTABILITY'='MUTABLE_LATEST'; ALTER TABLE gps_data SET 'CONSISTENCY'='strong';説明任意のタイムスタンプでデータ更新を許可するインデックスを使用する場合は、
MUTABILITYプロパティをMUTABLE_ALLに設定する必要があります。ALTER TABLE gps_data SET 'MUTABILITY' = 'MUTABLE_ALL';を実行します。 Mutability の分類の詳細については、「基本概念」をご参照ください。時空間セカンダリインデックスを作成します。 この例では、時空間データテーブルはすでに作成されています。 したがって、時空間セカンダリインデックスを作成することによってのみ、データクエリを高速化できます。 次の例では、空間列と時間列にインデックスを作成します。
CREATE INDEX idt ON gps_data (Z-ORDER(g,t));
指定された時空間範囲内の軌跡ポイントデータのクエリ
時空間関数 ST_Contains を使用して、空間範囲が POLYGON ((18 24, 20 24, 20 26, 18 26, 18 24)) で、時間範囲が 2021 年 1 月 1 日の 08:21 から 08:23 までの軌跡ポイントデータをクエリします。
時空間セカンダリインデックスの Z-ORDER 関数には g 列と t 列が含まれているため、クエリ条件には g 列と t 列の両方の範囲を含める必要があります。 時空間クエリの最適化については、「時空間クエリのパフォーマンスチューニング」をご参照ください。
SELECT id,t,ST_AsText(g),ship_name FROM gps_data WHERE ST_Contains(ST_GeomFromText('POLYGON ((18 24, 20 24, 20 26, 18 26, 18 24))'),g) AND t>'2021-01-01 08:21:00' AND t<'2021-01-01 08:23:00';次の結果が返されます。
+----+-------------------------------+------------------------+-----------+
| id | t | "ST_AsText"(g) | ship_name |
+----+-------------------------------+------------------------+-----------+
| 2 | 2021-01-01 08:22:20 +0000 UTC | POINT (19.07352 25.33) | ship002 |
+----+-------------------------------+------------------------+-----------+時空間関数の詳細については、「時空間関数の概要」をご参照ください。