Em tabelas distribuídas do PolarDB-X, consultas sem a chave de partição acionam uma varredura completa em todos os nós de dados. Isso reduz o desempenho ao limite de um único nó e elimina o dimensionamento linear. Um índice secundário global (GSI) elimina as varreduras completas de partição ao permitir definir um esquema de particionamento independente para o índice. Assim, qualquer coluna pode se tornar um caminho de consulta eficiente.
Como os GSIs funcionam
O PolarDB-X armazena os dados da tabela em vários nós de dados, particionados por uma chave específica. Consultas com a chave de partição são roteadas diretamente para a partição relevante. Já consultas sem essa chave se espalham por todas as partições.
Em sistemas com N nós de dados, uma consulta com chave de partição gera carga média de 1/N em cada nó. Uma varredura completa de partição impõe carga de 1 em todos os nós. Consequentemente, o teto de desempenho cai para o de um único nó e o sistema perde o dimensionamento linear.
Um GSI resolve esse problema ao atuar como uma tabela particionada especial que duplica colunas específicas da tabela primária. O particionamento horizontal usa uma chave definida pelo usuário, diferente da chave de partição da tabela primária. Quando uma consulta corresponde à chave de partição do GSI, o PolarDB-X a roteia para a partição relevante do GSI, recupera as linhas correspondentes e busca colunas adicionais na tabela primária. Isso evita a varredura completa da partição.
O PolarDB-X utiliza transações distribuídas para manter forte consistência de dados entre a tabela primária e seus GSIs.
Os GSIs também oferecem suporte a:
DDL online — crie, modifique e remova GSIs sem bloquear a tabela
Colunas de cobertura personalizadas — armazene colunas adicionais no GSI para reduzir ou eliminar buscas na tabela primária
Índices invisíveis — teste o efeito de um GSI nos planos de consulta sem expô-lo ao otimizador. Isso permite validar o desempenho do índice antes de habilitá-lo em produção
Tipos de GSI
GSI
Um GSI padrão particiona os dados do índice por uma coluna diferente da chave de partição da tabela primária. Se a consulta corresponder à chave de partição do GSI, o PolarDB-X a roteará para a partição relevante e consultará a tabela primária para obter as colunas restantes.
Example: A tabela user é particionada por user_id. Para viabilizar consultas eficientes por name, crie um GSI em 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);
Com o g_i_name implementado, consultas filtradas por name são roteadas para a partição correspondente do índice, em vez de varrer todas as partições de user.
UGSI
Um índice secundário global exclusivo (UGSI) possui todas as propriedades de um GSI padrão e aplica adicionalmente uma restrição UNIQUE global em toda a tabela distribuída.
Exemplo: A tabela user2 é particionada por user_id. Para garantir que phone seja globalmente exclusivo em todas as partições, crie um UGSI em phone.
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);
GSI clusterizado
Por padrão, um GSI clusterizado armazena todas as colunas da tabela primária, não apenas a chave do índice e as colunas de cobertura. Como todas as colunas estão presentes no índice, as consultas nunca precisam acessar a tabela primária, o que elimina totalmente a sobrecarga de busca.
A contrapartida é que um GSI clusterizado ocupa a mesma quantidade de espaço em disco que a tabela primária.
Exemplo: A tabela order_tbl é particionada por order_id. Para viabilizar consultas rápidas por user_id sem buscas na tabela primária, crie um GSI clusterizado em user_id.
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);
Ao consultar por user_id, o PolarDB-X roteia a consulta para a partição correspondente de cg_i_user e lê todos os dados necessários diretamente do índice.
Quando usar cada tipo
|
Cenário |
Tipo recomendado |
|
Consulta por coluna fora da chave de partição; busca na tabela primária aceitável |
GSI |
|
Consulta por coluna fora da chave de partição; coluna deve ser globalmente exclusiva |
UGSI |
|
Consulta por coluna fora da chave de partição; prioridade é eliminar sobrecarga de busca |
GSI clusterizado |
Desempenho
Os GSIs melhoram o desempenho de leitura, mas degradam o de escrita. Os benchmarks do Sysbench a seguir ilustram o impacto em escala.
Desempenho de leitura
| Tabela | Threads | QPS de select_random_ranges | Latência média (ms) | Percentil 95 (ms) | QPS de select_random_points | Latência média (ms) | Percentil 95 (ms) |
|---|---|---|---|---|---|---|---|
| Tabela particionada | 128 | 2.769,17 | 46,21 | 99,33 | 5.226,99 | 24,48 | 42,61 |
| 256 | 3.415,64 | 144,97 | 144,97 | 5.476,76 | 46,73 | 82,96 | |
| 512 | 3.272,46 | 156,31 | 257,95 | 5.290,67 | 96,72 | 179,94 | |
| 1024 | 2.453,16 | 416,12 | 539,71 | 5.165,31 | 198,07 | 404,61 | |
| Tabela particionada + GSI | 128 | 9.662,11 | 13,24 | 25,28 | 22.584,89 | 5,66 | 9,73 |
| 256 | 10.431,73 | 24,52 | 51,02 | 25.558,26 | 10,01 | 17,95 | |
| 512 | 15.634,51 | 32,72 | 73,13 | 27.116,56 | 18,86 | 39,65 | |
| 1024 | 22.948,76 | 44,53 | 108,68 | 32.509,87 | 31,43 | 73,13 |
Com um GSI na coluna de índice:
QPS de consulta de intervalo: 3.415,64 → 22.948,76 — 571% improvement
QPS de consulta pontual: 5.476,76 → 32.509,87 — 493% improvement
Desempenho de escrita
| Tabela | Threads | QPS somente escrita | Latência média (ms) | Percentil 95 (ms) | QPS leitura-escrita | Latência média (ms) | Percentil 95 (ms) |
|---|---|---|---|---|---|---|---|
| Tabela particionada | 128 | 86.548,12 | 8,87 | 10,27 | 113.655,28 | 22,52 | 26,2 |
| 256 | 115.774,71 | 13,26 | 19,29 | 149.677,52 | 34,19 | 44,17 | |
| 512 | 143.928,94 | 20,51 | 34,95 | 14.555,16 | 70,28 | 112,67 | |
| 1024 | 153.501,7 | 39,53 | 70,55 | 132.150,69 | 131,58 | 287,38 | |
| Tabela particionada + GSI | 128 | 52.069,22 | 14,25 | 18,28 | 90.074,59 | 28,41 | 33,72 |
| 256 | 66.250,79 | 23,17 | 32,53 | 114.420,32 | 44,73 | 57,87 | |
| 512 | 75.700,74 | 39,1 | 59,99 | 111.093,61 | 92,09 | 142,39 | |
| 1024 | 76.557,94 | 80,14 | 134,9 | 101.828,32 | 182,51 | 350,33 |
Com um GSI na coluna de índice:
QPS somente escrita: 153.501,7 → 76.557,94 — 50% reduction
QPS misto leitura-escrita: 149.677,52 → 114.420,32 — 23% reduction