為了提高時空查詢的性能,需要確保查詢條件能夠使用到時空索引,從而避免全表掃描。本文介紹時空查詢的優化方法。

時空查詢的優化

當查詢條件只有空間范圍或者包含空間范圍和時間范圍時,創建時空索引需要使用Z-ORDER索引函數對空間列或者時間列進行時空編碼,即Z-ORDER(geometry)或者Z-ORDER(geometry,time)類型。在查詢語句中請注意以下幾點:
  • Z-ORDER索引函數的入參會影響時空查詢的性能,查詢條件中必須包含Z-ORDER索引函數的所有列,才能使用時空索引。
  • 如果Z-ORDER索引函數對空間范圍和時間范圍組合進行時空編碼,那么查詢條件中必須同時包含時間的上限和下限,才能使用時空索引。
下表列舉了不同的Z-ORDER索引函數類型對查詢操作的影響,其中g為空間類型的列,t為時間類型的列。
查詢條件查詢語句Z-ORDER(g)Z-ORDER(g,t)
只有空間范圍SELECT id FROM point_table WHERE ST_Contains(ST_GeomFromText('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'),g);可以使用Z-ORDER索引函數加速查詢。不能使用Z-ORDER索引函數加速查詢,因為Z-ORDER索引函數是對g和t建立的索引,查詢條件必須同時包含空間范圍和時間范圍才能使用時空索引。
包含空間范圍和時間范圍SELECT id FROM point_table WHERE ST_Contains(ST_GeomFromText('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'),g) AND t>'2021-01-01 08:21:00' AND t<'2021-01-01 08:23:00';可以使用Z-ORDER索引函數加速查詢。可以使用Z-ORDER索引函數加速查詢。
SELECT id FROM point_table WHERE ST_Contains(ST_GeomFromText('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'),g) AND t > '2021-01-01 08:21:00';可以使用Z-ORDER索引函數加速查詢。不能使用Z-ORDER索引函數加速查詢,因為時間條件不是閉合范圍。

組合查詢的優化

如果查詢條件中包含時空范圍和其他列,為了加快時空查詢的速度,建議構建組合索引。組合索引是指主鍵索引或者二級索引中包含Z-ORDER索引函數和其他列,例如PRIMARY KEY(Z-ORDER(g,t), id)。由于Z-ORDER索引函數返回的是一個編碼值,可以將Z-ORDER當作一列。關于Lindorm寬表的組合索引介紹,請參見查詢優化

并行查詢的優化

在開啟并行查詢的條件下,可以使用Sharding來提高并行查詢的并行度,從而提高查詢性能。

Sharding是指將數據進行分片的方法。創建時空索引時使用Sharding可以使數據更加分散。同時,使用Sharding可以在寫入數據時將空間或時空相鄰的數據寫入到索引表的不同位置,進而寫入到數據庫物理存儲的不同分片中。

您可以通過Z-ORDER索引函數,為數據類型為點(Point)的列創建時空索引,并指定索引分片(Shard)的數量numShards,即Z-ORDER(Point, numShards)。指定numShards后,索引值相鄰的numShards條數據前會被依次加上0 - numShards-1前綴,并被寫入到索引表的不同位置。

以下示例對比了使用Sharding前后的查詢效率:

使用Sharding前:
  1. 對于數據類型為Point,數據量約為1.5億的示例表,創建不設置numShards參數的空間索引表table_noshard。
    CREATE TABLE table_noshard(id INT, g GEOMETRY(POINT), name VARCHAR, PRIMARY KEY(Z-ORDER(g)));
  2. 對空間索引表table_noshard開啟并行查詢。
    SELECT /*+_l_enable_parallel_(8)*/ id FROM table_noshard WHERE ST_Contains(ST_GeomFromText('POLYGON((...))'), g);

    返回結果為2058894,耗時10986ms

使用Sharding后:
  1. 創建對照組。對同一示例表,建立numShards值為8的空間索引表table_shard8。
    CREATE TABLE table_shard8(id INT, g GEOMETRY(POINT), name VARCHAR, PRIMARY KEY(Z-ORDER(g, 8)));
  2. 對空間索引表table_shard8開啟并行查詢。
    SELECT /*+_l_enable_parallel_(8)*/ id FROM table_shard8 WHERE ST_Contains(ST_GeomFromText('POLYGON((...))'), g);

    返回結果為2058894,耗時2501ms

可以看到,兩種方式的返回結果完全相同,但設置了numShards參數后并行查詢的耗時明顯縮短,查詢效率大幅提升。

不規則范圍查詢的優化

創建時空索引后,當查詢范圍的形狀與其矩形外包框(索引過濾范圍)相差較大時,索引過濾的效果并不理想,如下圖所示。不規則范圍查詢

當數據量較大時,可以通過設置HINT的/*+_l_enable_enhanced_filter_*/ 參數來開啟索引過濾增強功能。

例如,為表gtest(g列已創建時空索引,POLYGON((...))為不規則范圍)開啟索引過濾增強功能:
SELECT /*+_l_enable_enhanced_filter_*/ id FROM gtest WHERE ST_Contains(ST_GeomFromText('POLYGON((...))'), g);
說明 索引過濾增強功能默認不開啟,在數據量較小的情況下無需使用。