全部產品
Search
文件中心

PolarDB:全域二級索引(GSI)

更新時間:Oct 11, 2024

本文介紹了全域二級索引的原理、特性和類型。

概述

全域二級索引(Global Secondary Index,簡稱GSI)是PolarDB-X中的一項重要特性,相比於本地二級索引,全域二級索引中的資料按照指定的分區方式分布在各個儲存節點上。通過全域二級索引,使用者能夠按需增加分區維度、提供全域唯一約束等。

原理和特性

在分散式資料庫的分區表中,資料被按照建表時指定的分區鍵進行路由和儲存,因此包含分區鍵的查詢可以快速定位到一個具體分區,而其它查詢則需要全分區掃描。對於分散式資料庫而言,全分區掃描除了會增加慢查詢數量降低系統吞吐,還可能導致系統喪失線性擴充能力,因此需要盡量避免全分區掃描。

舉例來說,當查詢語句包含分區鍵時,單個邏輯查詢只會被路由到一個具體分區,假設有N個儲存節點,平均來看1個邏輯查詢給單個儲存節點施加的查詢負載僅為1/N;當查詢語句不含分區鍵時會引起全分區掃描,即單個查詢會被路由到所有分區,平均來看1個邏輯查詢給單個儲存節點施加的查詢負載為1,單個儲存節點的效能上限就是整個分散式資料庫的效能上限,系統失去了線性擴充能力。

PolarDB-X提供了全域二級索引以解決上述問題。在PolarDB-X中,GSI可以視為一個特殊的分區表,它冗餘了主表上的部分列的資料。與普通分區表類似,GSI按照使用者指定的分區規則水平分割為若干個分區,分布在各個儲存節點上。當一個查詢不含主表分區鍵但包含GSI的分區鍵時,PolarDB-X通過先檢索GSI的單個分區,然後回表的方式避免全分區掃描。

PolarDB-X使用分散式交易維護主表和GSI之間資料的強一致。

此外,GSI還支援以下特性:

  • 支援線上變更,建立、刪除GSI無需鎖表。

  • 使用者可自訂覆蓋列,減少回表操作開銷。

  • 支援invisible index。

類型

全域二級索引(Global Secondary Index 簡稱GSI)

全域二級索引可以提供和主表不同的分區方式,當查詢SQL的條件中未包含主表的分區鍵但包含了GSI的分區鍵時,仍可以避免全分區掃描。

比如對於下面的使用者表user_tbl, 如果既希望按照user_id查詢,又希望按照使用者名稱name查詢,就可以建立全域二級索引 g_i_name,在按照使用者名稱name查詢的時候避免全分區掃描。

CREATE TABLE user(
 user_id bigint,
 name varchar(10),
 addr varchar(30),
 GLOBAL INDEX `g_i_name` (name) PARTITION BY HASH(name),
 PRIMARY KEY(user_id)
) PARTITION BY KEY(user_id);

全域唯一索引(Unique Global Secondary Index 簡稱UGSI)

全域唯一索引是特殊的GSI,它不僅有普通GSI的性質,還能實現全域唯一約束。

比如對於下面的使用者表user2,如果要求使用者手機號全域唯一,那麼可以建立一個phone欄位為索引鍵的UGSI。

CREATE TABLE user2(
 user_id bigint,
 phone varchar(20),
 addr varchar(30),
 UNIQUE GLOBAL INDEX `g_i_phone`(phone)  PARTITION BY HASH(phone), 
 PRIMARY KEY(user_id)
) PARTITION BY KEY(user_id);

全域聚簇索引 (Clustered Global Secondary Index 簡稱Clustered GSI)

全域聚簇索引是特殊的GSI,它預設冗餘了主表的全部列(該索引所佔磁碟空間等於主表所佔磁碟空間)。如果既希望避免全分區掃描,又希望避免回表開銷,可以使用全域聚簇索引。

比如對於訂單表order_tbl,希望支援按照user_id或order_id來查詢,且希望避免用user_id查詢訂單時回表,就可以建立一個以user_id為索引鍵的全域聚簇索引cg_i_user。以user_id為條件查詢訂單資訊時,PolarDB-X會將查詢路由到cg_i_user上的一個特定分區,又因為cg_i_user上有主表的所有資料,因此無需回表。

CREATE TABLE order_tbl(
 order_id bigint,
 user_id bigint,
 addr varchar(30),
 info text,
 create_time datetime,
 CLUSTERED INDEX `cg_i_user`(user_id) PARTITION BY HASH(user_id), 
 PRIMARY KEY(order_id)
) PARTITION BY KEY(order_id);

效能

全域索引對讀寫效能的影響,與具體業務情境有比較大關係,本質上是犧牲一部分寫入效能換取讀效能的大幅提升,下面以Sysbench情境為例,展示該情境下GSI對讀寫吞吐的影響。

讀取效能資料

Table

Threads

Sysbench SeIect_random_ranges 情境

Sysbench SeIect_random_points 情境

QPS

Avg Latency

95% Latency

QPS

Avg Latency

95% Latency

分區表

128

2769.17

46.21

99.33

5226.99

24.48

42.61

256

3415.64

144.97

144.97

5476.76

46.73

82.96

512

3272.46

156.31

257.95

5290.67

96.72

179.94

1024

2453.16

416.12

539.71

5165.31

198.07

404.61

分區表+GSI

128

9662.11

13.24

25.28

22584.89

5.66

9.73

256

10431.73

24.52

51.02

25558.26

10.01

17.95

512

15634.51

32.72

73.13

27116.56

18.86

39.65

1024

229448.76

44.53

108.68

32509.87

31.43

73.13

增加一個全域索引:

  • Select_random_ranges情境QPS:3415.64 -> 22948.76, range查詢QPS提升571%。

  • Select_random_points情境QPS:5476 -> 32509.87, 點查QPS提升493%。

結論:通過全域索引可以提升Sysbench在索引列k上的查詢效能。

寫入效能資料

Table

Threads

Sysbench SeIect_random_ranges 情境

Sysbench SeIect_random_points 情境

QPS

Avg Latency

95% Latency

QPS

Avg Latency

95% Latency

分區表

128

86548.12

8.87

10.27

113655.28

22.52

26.2

256

115774.71

13.26

19.29

149677.52

34.19

44.17

512

143928.94

20.51

34.95

14555.16

70.28

112.67

1024

153501.7

39.53

70.55

132150.69

131.58

287.38

分區表+GSI

128

52069.22

14.25

18.28

90074.59

28.41

33.72

256

66250.79

23.17

32.53

114420.32

44.73

57.87

512

75700.74

39.1

59.99

111093.61

92.09

142.39

1024

76557.94

80.14

134.9

101828.32

182.51

350.33

增加一個全域索引:

  • WriteOnly情境QPS:153501.7 -> 76557.94,寫入QPS下降50%。

  • ReadWrite情境QPS:149677.52 -> 114420.32,讀寫混合QPS下降23%。

結論:增加一個全域索引,Sysbench寫入效能有下降。

相關文檔

如何使用全域二級索引

聚簇索引