Lindorm GanosBase は、時系列順で並んでいないポイントを時間順にソートし、それらを軌道にアセンブルして軌道メトリックを算出する時空間集計関数を提供します。これらの関数は、車両インターネット(IoV)、GIS、IoT アプリケーションなど、大規模な時空間ワークロードおよび軌道分析を必要とするユースケースに適用できます。
前提条件
エンジン:LindormTable 2.6.5 以降。ご利用のバージョンを確認またはマイナーエンジンバージョンをアップグレードするには、「LindormTable のリリースノート」および「Lindorm インスタンスのマイナーエンジンバージョンのアップグレード」をご参照ください。
SQL バージョン:Lindorm SQL 2.6.8 以降。ご利用のバージョンを確認するには、「SQL バージョン」をご参照ください。
関数一覧
| 関数 | 説明 |
|---|---|
ST_Length_Rows | 時系列順で並んでいないポイントを時間順にソートし、それらを軌道にアセンブルして、球面距離による軌道長(メートル単位)を返します。 |
ST_Resample | 時系列順で並んでいないポイントを時間順にソートし、時間的・空間的なしきい値に基づいてポイントをダウンサンプリングして、ダウンサンプリング後の軌道を JSON 文字列として返します。 |
ST_TrajectoryProfile | 時系列順で並んでいないポイントを時間順にソートし、それらを軌道にアセンブルして、時間的なしきい値に基づいて軌道をセグメント化し、各セグメントの開始点および終了点の座標とタイムスタンプを返します。 |
ST_Length_Rows
時系列順で並んでいないポイントを時間順にソートし、それらを軌道にアセンブルして、球面距離による軌道長(メートル単位)を返します。
構文
double ST_Length_Rows(point column)パラメーター
| パラメーター | 説明 |
|---|---|
point column | 処理対象のジオメトリ列。POINT オブジェクトを含む必要があります。 |
使用上の注意事項
ST_Length_Rowsを使用する際は、GROUP BY句と組み合わせて、列(例:車両 ID)ごとにグループ化された軌道長を算出してください。正しい並び順は、プライマリキーのソート順に依存します。行が正しい移動順序で格納およびスキャンされるよう、エンティティ識別子(例:車両 ID)とタイムスタンプ列を含む複合プライマリキーを定義してください。プライマリキーが正しい並び順を保証しない場合、返される軌道長は不正確になる可能性があります。
例
以下の例では、次のように作成およびデータ入力された test_len テーブルを使用します:
CREATE TABLE test_len (
carid VARCHAR,
collect_time TIMESTAMP,
p GEOMETRY(POINT),
PRIMARY KEY(carid, collect_time)
);
INSERT INTO test_len (carid, collect_time, p) VALUES
('car1', '2023-09-12 00:04:02', ST_GeomFromText('POINT (111.40269 35.61695)')),
('car1', '2023-09-12 00:09:07', ST_GeomFromText('POINT (111.40127 35.616096)')),
('car1', '2023-09-12 00:14:03', ST_GeomFromText('POINT (111.400604 35.616013)')),
('car1', '2023-09-12 00:20:13', ST_GeomFromText('POINT (111.399734 35.613983)')),
('car1', '2023-09-12 00:27:21', ST_GeomFromText('POINT (111.40217 35.616386)')),
('car2', '2023-09-12 00:27:21', ST_GeomFromText('POINT (111.40217 35.616386)'));プライマリキー (carid, collect_time) により、各車両ごとにポイントが昇順の時間順で格納されるため、軌道が正しくアセンブルされます。
例 1:car1 の軌道について球面距離による軌道長を算出します。
SELECT ST_LENGTH_ROWS(p) FROM test_len WHERE carid = 'car1';結果:
+--------------------+
| st_length_rows(p) |
+--------------------+
| 805.55323541493414 |
+--------------------+例 2:車両 ID ごとにグループ化した各車両の球面距離による軌道長を算出します。
SELECT carid, ST_LENGTH_ROWS(p) AS len
FROM test_len
WHERE carid <= 'car2'
GROUP BY carid;結果:
+-------+--------------------+
| carid | len |
+-------+--------------------+
| car1 | 805.55323541493414 |
| car2 | 0 |
+-------+--------------------+ST_Resample
時系列順で並んでいないポイントを時間順にソートし、時間的・空間的なしきい値に基づいてダウンサンプリングします。ダウンサンプリング後の軌道を JSON 文字列として返します。
構文
バリアント 1: ポイント列の入力。
String ST_Resample(String geomColumnName, String timeColumnName, String config)変形 2:経度列および緯度列を個別に指定します。
String ST_Resample(String xColumnName, String yColumnName, String timeColumnName, String config)パラメーター
| パラメーター | 説明 |
|---|---|
geomColumnName | POINT ジオメトリ列。ポイントデータがジオメトリオブジェクトとして格納されている場合(変形 1)に使用します。 |
xColumnName | 経度列(DOUBLE 型)。yColumnName とペアで使用します。ポイントデータが個別の経度および緯度値として格納されている場合(変形 2)に使用します。 |
yColumnName | 緯度列(DOUBLE 型)。xColumnName とペアで使用します(変形 2)。 |
timeColumnName | ポイントを昇順でソートする際に使用する時間列。TIME、TIMESTAMP、LONG 型をサポートします。LONG 型の場合、値はミリ秒単位である必要があります。 |
config | JSON 形式(STRING 型)のダウンサンプリング構成。形式: {"parameter": value, ...}。利用可能なパラメーターについては、以下の表をご参照ください。 |
ダウンサンプリングパラメーター(config)
| パラメーター | 型 | デフォルト値 | 説明 |
|---|---|---|---|
downsample_time | INT または LONG | -1(無効) | 時間的なダウンサンプリングしきい値(ミリ秒単位)。出力内の隣接するポイント間の時間間隔は、この値より大きくなります。 |
downsample_distance | INT、LONG、FLOAT、または DOUBLE | -1.0(無効) | 空間的なダウンサンプリングしきい値。このパラメーター値に基づく指定アルゴリズムを用いて、軌道のジオメトリを簡略化します。このパラメーターの単位は、座標の単位と同じです。 |
simplifier | STRING | topologypreserving | 簡略化アルゴリズム。有効な値: vw(Visvalingam-Whyatt)、dp(Douglas-Peucker)、topologypreserving(トポロジーを保持する Douglas-Peucker;ただし downsample_distance が指定されている場合のみ有効)。 |
返される値
時間順にソートされたダウンサンプリング済み軌道ポイントの JSON 配列:
[{"x": <longitude>, "y": <latitude>, "t": <time>}, ...]使用上の注意事項
特定のエンティティまたは時間範囲に対応する軌道ポイントを選択するため、フィルター条件を適用してください。
ST_Resampleは、フルテーブルではなく、フィルター適用後の結果セットに対して動作します。ST_ResampleはGROUP BY句と併用できません。
例
以下の例では、次のように作成およびデータ入力された gps_points テーブルを使用します:
CREATE TABLE gps_points (
account_id VARCHAR,
collect_time TIMESTAMP,
gps_point GEOMETRY(POINT),
PRIMARY KEY(account_id, collect_time)
);
INSERT INTO gps_points (account_id, collect_time, gps_point) VALUES
('001', '2023-11-10 11:00:30', ST_MakePoint(113.665431, 34.773)),
('001', '2023-11-10 11:00:31', ST_MakePoint(113.665432, 34.773)),
('001', '2023-11-10 11:00:32', ST_MakePoint(113.665433, 34.773)),
('001', '2023-11-10 11:00:33', ST_MakePoint(113.665434, 34.774));アカウント 001 の軌道を 24 時間のウィンドウ内でクエリし、空間しきい値 0.0001 を持つ Visvalingam-Whyatt アルゴリズムでダウンサンプリングします:
SELECT ST_Resample(
gps_point,
collect_time,
'{"downsample_distance": 0.0001, "simplifier": "vw"}'
) AS resampled_traj
FROM gps_points
WHERE account_id = '001'
AND collect_time >= '2023-11-10 00:00:00'
AND collect_time <= '2023-11-11 00:00:00';結果:
+-----------------------------------------------------------------------------------------------------+
| resampled_traj |
+-----------------------------------------------------------------------------------------------------+
| [{"x":113.665431,"y":34.773,"t":"2023-11-10 11:00:30.0"},{"x":113.665434,"y":34.774,"t":"2023-11-10 11:00:33.0"}] |
+-----------------------------------------------------------------------------------------------------+ST_TrajectoryProfile
時系列順で並んでいないポイントを時間順にソートし、それらを軌道にアセンブルして、時間的なギャップしきい値に基づいて軌道をセグメント化し、各セグメントの開始点および終了点の座標とタイムスタンプを返します。
ST_TrajectoryProfile は、通常、ST_DWithinSphere などの空間関係関数と組み合わせて使用され、各軌道セグメント内で移動エンティティが定義済みエリアに最初に進入し、最後に退出するタイミングを特定します。
構文
バリアント 1: ポイント列を入力として。
String ST_TrajectoryProfile(String geomColumnName, String timeColumnName, long thresh)変形 2:経度列および緯度列を個別に指定します。
String ST_TrajectoryProfile(String xColumnName, String yColumnName, String timeColumnName, long thresh)パラメーター
| パラメーター | 説明 |
|---|---|
geomColumnName | POINT ジオメトリ列。ポイントデータがジオメトリオブジェクトとして保存されている場合(バリアント 1)に、このパラメーターを使用します。 |
xColumnName | 経度列(DOUBLE 型)。yColumnName とペアで使用します。ポイントデータが個別の経度および緯度値として格納されている場合(変形 2)に使用します。 |
yColumnName | 緯度列(DOUBLE 型)。xColumnName とペアで使用します(変形 2)。 |
timeColumnName | 時間列。ポイントはこの列の昇順でソートされます。 |
thresh | (任意)同一軌道セグメントに属する 2 つの隣接ポイント間の最大時間ギャップ(ミリ秒単位)。2 つのポイント間のギャップがこのしきい値を超える場合、それらは異なるセグメントに配置されます。デフォルト値:10000(10 秒)。 |
返される値
各キーがセグメントインデックス(0 基準)であり、各値がセグメントの境界座標およびタイムスタンプを含む JSON 文字列である JSON オブジェクト:
{
"0": "{\"startX\": <longitude>, \"startY\": <latitude>, \"startTime\": <epoch ms>, \"endX\": <longitude>, \"endY\": <latitude>, \"endTime\": <epoch ms>}",
"1": "...",
...
}使用上の注意事項
ST_TrajectoryProfileを使用する際は、エンティティ(例:車両 ID)ごとにポイントを軌道に集約するために、GROUP BY句と併用する必要があります。セカンダリインデックスを使用する場合、クエリで参照されるすべての列(
GROUP BYキー、フィルター条件列、関数パラメーター列)を、インデックスの含まれる列として追加してください。これにより、ベーステーブルのスキャンを回避できます。たとえば、クエリでcaridでグループ化し、関数にpおよびcollect_timeを渡す場合、これら 3 つの列をすべてインデックスに含めてください。
例
以下の例では、次のように作成およびデータ入力された test_traj テーブルを使用します:
CREATE TABLE test_traj (
carid VARCHAR,
collect_time TIMESTAMP,
p GEOMETRY(POINT),
status VARCHAR,
PRIMARY KEY(z-order(p), carid, collect_time)
);
INSERT INTO test_traj (carid, collect_time, p, status) VALUES
('car1', '2023-09-12 00:04:02', ST_GeomFromText('POINT (111.40269 35.61695)'), 'normal'),
('car1', '2023-09-12 00:09:07', ST_GeomFromText('POINT (111.40127 35.616096)'), 'normal'),
('car1', '2023-09-12 00:14:03', ST_GeomFromText('POINT (111.400604 35.616013)'), 'normal'),
('car1', '2023-09-12 00:20:13', ST_GeomFromText('POINT (111.399734 35.613983)'), 'normal'),
('car1', '2023-09-12 00:27:21', ST_GeomFromText('POINT (111.40217 35.616386)'), 'normal'),
('car2', '2023-09-12 00:27:21', ST_GeomFromText('POINT (111.40217 35.616386)'), 'normal');各車両について、POINT (111.40217 35.616386) の半径 100 メートル以内で、2023-09-12 00:09:07 から 2023-09-20 00:09:07 の期間に収集されたポイントのうち、最初の進入点および最後の退出点を特定します。セグメント間のギャップしきい値には 30,000 ミリ秒(30 秒)を使用します:
SELECT
carid,
ST_TrajectoryProfile(p, collect_time, 30000) AS trajprofile
FROM test_traj
WHERE ST_DWithinSphere(ST_GeomFromText('POINT (111.40217 35.616386)'), p, 100.0)
AND collect_time >= '2023-09-12 00:09:07'
AND collect_time <= '2023-09-20 00:09:07'
GROUP BY carid;クエリでセカンダリインデックスを使用する場合、carid、p、および collect_time をインデックスの含まれる列として追加することで、ベーステーブルのスキャンを回避できます。
結果:
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| carid | trajprofile |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| car1 | {"0":"{\"endY\":35.616096,\"endX\":111.40127,\"startY\":35.616096,\"startTime\":1694448547000,\"startX\":111.40127,\"endTime\":1694448547000}","1":"{\"endY\":35.616386,\"endX\":111.40217,\"startY\":35.616386,\"startTime\":1694449641000,\"startX\":111.40217,\"endTime\":1694449641000}"} |
| car2 | {"0":"{\"endY\":35.616386,\"endX\":111.40217,\"startY\":35.616386,\"startTime\":1694449641000,\"startX\":111.40217,\"endTime\":1694449641000}"} |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+car1 は検索エリア内に 2 つの軌道セグメント(セグメント 0 およびセグメント 1)を持ちます。car2 はエリア内に 1 つのポイントしか持たず、そのポイントは開始座標と終了座標およびタイムスタンプが一致する単一のセグメント(セグメント 0)を形成します。