文档

全局二级索引(GSI)

更新时间:

本文介绍了全局二级索引的原理、特性和类型。

概述

全局二级索引(Global Secondary Index,简称GSI)是PolarDB-X中的一项重要特性,相比于本地二级索引,全局二级索引中的数据按照指定的分区方式分布在各个存储节点上。通过全局二级索引,用户能够按需增加分区维度、提供全局唯一约束等。

原理和特性

在分布式数据库的分区表中,数据被按照建表时指定的分区键进行路由和存储,因此包含分区键的查询可以快速定位到一个具体分区,而其它查询则需要全分区扫描。对于分布式数据库而言,全分区扫描除了会增加慢查询数量降低系统吞吐,还可能导致系统丧失线性扩展能力,因此需要尽量避免全分区扫描。

举例来说,当查询语句包含分区键时,单个逻辑查询只会被路由到一个具体分区,假设有N个存储节点,平均来看1个逻辑查询给单个存储节点施加的查询负载仅为1/N;当查询语句不含分区键时会引起全分区扫描,即单个查询会被路由到所有分区,平均来看1个逻辑查询给单个存储节点施加的查询负载为1,单个存储节点的性能上限就是整个分布式数据库的性能上限,系统失去了线性扩展能力。

PolarDB-X提供了全局二级索引以解决上述问题。在PolarDB-X中,GSI可以视为一个特殊的分区表,它冗余了主表上的部分列的数据。与普通分区表类似,GSI按照用户指定的分区规则水平拆分为若干个分区,分布在各个存储节点上。当一个查询不含主表分区键但包含GSI的分区键时,PolarDB-X通过先检索GSI的单个分区,然后回表的方式避免全分片扫描。

幻灯片1.JPG

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` 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` 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` PARTITION BY HASH(user_id), 
 PRIMARY KEY(order_id)
) PARTITION BY KEY(order_id);

性能

全局索引对读写性能的影响,与具体业务场景有比较大关系,本质上是牺牲一部分写入性能换取读性能的大幅提升,下面以Sysbench场景为例,展示该场景下GSI对读写吞吐的影响。

1.读取性能数据

image.png

增加一个全局索引:

  • Select_random_ranges场景QPS:3415.64 -> 22948.76, range查询QPS提升571%。

  • Select_random_points场景QPS:5476 -> 32509.87, 点查QPS提升493%。

结论:通过全局索引可以提升Sysbench在索引列k上的查询性能。

2. 写入性能数据

image.png

增加一个全局索引:

  • WriteOnly场景QPS:153501.7 -> 76557.94, 写入QPS下降50%。

  • ReadWrite场景QPS:149677.52 -> 114420.32, 读写混合QPS下降23%。

结论:增加一个全局索引,Sysbench写入性能有下降。

相关文档

如何使用全局二级索引

聚簇索引