本文以車聯網軌跡查詢場景為例,通過Lindorm Ganos SQL將采集的軌跡點寫入Lindorm寬表中并根據時空范圍進行快速查詢。
前提條件
已安裝Java環境,要求安裝JDK 1.8及以上版本。
已獲取Lindorm寬表SQL的連接地址并配置白名單,具體操作,請參見訪問實例。
操作流程
從創建時空數據表到根據時空范圍查詢軌跡,您需要完成以下操作:
創建時空數據表并寫入數據
通過Lindorm-cli連接寬表引擎并寫入數據
連接Lindorm寬表引擎。以通過Lindorm-cli連接寬表引擎為例(客戶端部署在Linux)。
如果您需要使用JDBC連接方式,請參見通過Lindorm寬表SQL Java API連接并使用寬表引擎。
解壓Lindorm-cli壓縮包。
獲取連接信息并執行下述命令連接Lindorm寬表。
./lindorm-cli -url <jdbc url> -username <用戶名> -password <密碼>
參數
示例值
獲取方法
jdbc url
jdbc:lindorm:table:url=http://ld-bp17j28j2y7pm****-proxy-lindorm-pub.lindorm.rds.aliyuncs.com:30060
Lindorm寬表SQL的連接地址,具體獲取方法請參見訪問實例。
用戶名
root
您可以通過云原生多模數據庫 Lindorm集群管理系統查看用戶名,如果您忘記對應的密碼,可以在集群管理系統中修改密碼,具體操作請參見修改用戶密碼。
密碼
root
返回如下結果:
Connected to jdbc:lindorm:table:url=http://ld-bp17j28j2y7pm****-proxy-lindorm-pub.lindorm.rds.aliyuncs.com:30060 lindorm-cli version: 1.0.15
通過以下兩種方式創建時空數據表。
時空數據表是用來存儲軌跡點的。軌跡點包括經度x、緯度y和時間t三類信息,其中x和y數據在Lindorm Ganos中有兩種存儲方式。存儲方式和特點如下:
存儲方式
特點
使用空間數據類型
Geometry(Point)
將x和y數據打包存儲在一列。高性能。
使用普通點坐標的方式將x和y數據分別存儲在兩列。
歷史數據以x、y兩列分開存儲,但性能會有損失。
使用空間數據類型
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)
PRIMARY KEY由
id
和t
組成。使用普通點坐標的方式將x、y和t數據分別存儲在三列。創建時空數據表語句如下:
CREATE TABLE gps_data_point (id int, x double, y double, t timestamp, ship_name varchar, PRIMARY KEY(id, t));
通過以下兩種方式單次寫入軌跡點數據。
使用時空函數
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
來構造軌跡點數據,軌跡點的格式使用WKT(Well-known Text)標準格式。但是通過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');
可選:通過以下兩種方式批量寫入軌跡點數據。
使用時空函數
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連接寬表引擎并寫入數據
與Lindorm SQL寫入其他數據類型一樣,寫入時空類型的數據時同樣支持通過參數化查詢的方式進行綁參寫入。下面是一個以Java JDBC通過PreapredStatement接口的參數化查詢方式寫入時空數據的Java代碼示例。
// 建立連接
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年01月01號08點21分~2021年01月01號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 |
+----+-------------------------------+------------------------+-----------+
更多時空函數請參見函數概覽。