Projeto da estrutura da tabela
Antes de otimizar uma tabela, você precisa entender a estrutura da tabela. Durante o design do banco de dados, alguns fatores-chave sobre o design da tabela afetarão muito o desempenho de consulta subsequente do banco de dados. O design da tabela também afeta o armazenamento de dados. O design da tabela científica reduz as operações de I/O e minimiza o uso de memória, melhorando o desempenho da consulta.
Esta seção descreve como otimizar o desempenho da tabela no GaussDB(DWS) projetando corretamente a estrutura da tabela (por exemplo, configurando o modo de armazenamento da tabela, o nível de compactação, o modo de distribuição, a coluna de distribuição, as tabelas particionadas e o agrupamento local).
Selecionar um tipo de armazenamento
Selecionar um modelo para armazenamento de tabela é o primeiro passo da definição de tabela. Selecione um modelo de armazenamento adequado para o seu serviço com base na tabela abaixo.
Geralmente, se uma tabela contém muitas colunas (chamada de tabela ampla) e sua consulta envolve apenas algumas colunas, o armazenamento de colunas é recomendado. Se uma tabela contiver apenas algumas colunas e uma consulta que envolve a maioria das colunas, recomenda-se o armazenamento de linhas.
Modelo de armazenamento |
Cenário de aplicação |
---|---|
Armazenamento de linha |
Consulta de ponto (consulta baseada em índice simples que retorna apenas alguns registros). Consulta envolvendo muitas operações INSERT, UPDATE e DELETE. |
Armazenamento de coluna |
Consulta de análise de estatísticas, na qual operações, como group e join, são executadas muitas vezes. |
O armazenamento de linha/coluna de uma tabela é especificado pelo atributo orientation na definição da tabela. O valor row indica uma tabela de armazenamento de linha e column indica uma tabela de armazenamento de coluna. O valor padrão é row.
Compressão de tabela
A compactação de tabela pode ser ativada quando uma tabela é criada. A compactação de tabela permite que os dados da tabela sejam armazenados em formato compactado para reduzir o uso de memória.
Em cenários em que a I/O é grande (muitos dados são lidos e gravados) e a CPU é suficiente (poucos dados são computados), selecione uma alta taxa de compactação. Em cenários em que a I/O é pequena e a CPU é insuficiente, selecione uma taxa de compactação baixa. Com base neste princípio, é aconselhável selecionar diferentes taxas de compressão e testar e comparar os resultados para selecionar a taxa de compressão ideal, conforme necessário. Especifique uma taxa de compressão usando o parâmetro COMPRESSION. Os valores suportados são os seguintes:
- O valor válido das tabelas de armazenamento de colunas é YES, NO, LOW, MIDDLE ou HIGH, e o valor padrão é LOW.
- Os valores válidos de tabelas de armazenamento de linha são YES e NO, e o padrão é NO. (A função de compactação de tabela de armazenamento de linha não é colocada em uso comercial. Para usar essa função, entre em contato com o suporte técnico.)
Os cenários de serviço aplicáveis a cada nível de compactação são descritos na tabela a seguir.
Nível de compressão |
Cenário de aplicação |
---|---|
LOW |
O uso da CPU do sistema é alto e o espaço de armazenamento em disco é suficiente. |
MIDDLE |
O uso da CPU do sistema é moderado e o espaço de armazenamento em disco é insuficiente. |
HIGH |
O uso da CPU do sistema é baixo e o espaço de armazenamento em disco é insuficiente. |
Selecionar um modo de distribuição
GaussDB(DWS) suporta os seguintes modos de distribuição: replication, hash e Round-robin.
Round-robin é suportado no cluster 8.1.2 e posterior.
Política |
Descrição |
Cenário de aplicação |
Vantagens/desvantagens |
---|---|---|---|
Replication |
Os dados completos em uma tabela são armazenados em cada DN no cluster. |
Pequenas tabelas e tabelas de dimensões |
|
Hash |
Os dados da tabela são distribuídos em todos os DNs no cluster. |
Tabelas de fatos contendo uma grande quantidade de dados |
|
Polling (Round-robin) |
Cada linha na tabela é enviada a cada DN por sua vez. Os dados podem ser distribuídos uniformemente em cada DN. |
Tabelas de fatos que contêm uma grande quantidade de dados e não conseguem encontrar uma chave de distribuição adequada no modo hash |
|
Selecionar uma chave de distribuição
Se o modo de distribuição hash for usado, uma chave de distribuição deve ser especificada para a tabela de usuário. Se um registro for inserido, o sistema executará o cálculo de hash com base nos valores na coluna de distribuição e, em seguida, armazenará os dados no DN relacionado.
Selecione uma chave de distribuição de hash com base nos seguintes princípios:
- Os valores da chave de distribuição devem ser discretos para que os dados possam ser distribuídos uniformemente em cada DN. Você pode selecionar a chave primária da tabela como a chave de distribuição. Por exemplo, para uma tabela de informações da pessoa, escolha a coluna do número de ID como a chave de distribuição.
- Não selecione a coluna onde existe um filtro constante. Por exemplo, se uma restrição constante (por exemplo, zqdh= '000001') existe na coluna zqdh em algumas consultas na tabela dwcjk, não é aconselhável usar zqdh como a chave de distribuição.
- Com os princípios acima atendidos, você pode selecionar condições de junção como chaves de distribuição, para que as tarefas de junção possam ser enviadas para DNs para execução, reduzindo a quantidade de dados transferidos entre os DNs.
Para uma tabela hash, uma chave de distribuição imprópria pode causar distorção de dados ou desempenho ruim de I/O em determinados DNs. Portanto, você precisa verificar a tabela para garantir que os dados sejam distribuídos uniformemente em cada DN. Você pode executar as seguintes instruções SQL para verificar a distorção de dados:
1 2 3 4 5
SELECT xc_node_id, count(1) FROM tablename GROUP BY xc_node_id ORDER BY xc_node_id desc;
xc_node_id corresponde a um DN. Geralmente, mais de 5% de diferença entre a quantidade de dados em diferentes DNs é considerada como distorção de dados. Se a diferença for superior a 10%, escolha outra chave de distribuição.
- Não é aconselhável adicionar uma coluna como uma chave de distribuição, especialmente adicionar uma nova coluna e usar o valor de SEQUENCE para preencher a coluna. (Sequências podem causar gargalos de desempenho e custos de manutenção desnecessários.)
Usar tabelas particionadas
O particionamento refere-se a dividir o que é logicamente uma grande tabela em pedaços físicos menores com base em esquemas específicos. A tabela baseada na lógica é chamada de tabela particionada, e uma parte física é chamada de partição. Os dados são armazenados nessas partes físicas menores, ou seja, partições, em vez da tabela particionada lógica maior. Uma tabela particionada tem as seguintes vantagens sobre uma tabela comum:
- Alto desempenho de consulta: o sistema consulta apenas as partições em questão, em vez de toda a tabela, melhorando a eficiência da consulta.
- Alta disponibilidade: se uma partição estiver com defeito, os dados nas outras partições ainda estarão disponíveis.
- Manutenção fácil: você só precisa corrigir a partição defeituosa.
As tabelas particionadas suportadas pelo GaussDB(DWS) incluem tabelas particionadas por intervalo e tabelas particionadas por lista. (As tabelas particionadas por lista são suportadas apenas no cluster 8.1.3).
Usar clustering parcial
Chave de cluster parcial é a tecnologia baseada em coluna. Ela pode minimizar ou maximizar índices esparsos para filtrar rapidamente tabelas base. Chave de cluster parcial pode especificar várias colunas, mas é aconselhável especificar não mais do que duas colunas. Use os seguintes princípios para especificar colunas:
- As colunas selecionadas devem ser restritas por expressões simples em tabelas base. Tais restrições são geralmente representadas por Col, Op e Const. Col especifica o nome da coluna, Op especifica operadores, (incluindo =, >, >=, <= e <) Const especifica constantes.
- Selecione colunas que são frequentemente selecionadas (para filtrar muito mais dados indesejados) em expressões simples.
- Liste as colunas selecionadas com menos frequência na parte superior.
- Liste as colunas do tipo enumerado na parte superior.
Selecionar um tipo de dados
Você pode usar tipos de dados com os seguintes recursos para melhorar a eficiência:
- Tipos de dados que aumentam a eficiência da execução
Geralmente, o cálculo de inteiros (incluindo cálculos de comparação comuns, como o =, >, <, ≥, ≤ e ≠ e GROUP BY) é mais eficiente do que o de cadeias e números de ponto flutuante. Por exemplo, se você precisar executar uma consulta de ponto em uma tabela de armazenamento de colunas cuja coluna NUMERIC é usada como critério de filtro, a consulta levará mais de 10 segundos. Se você alterar o tipo de dados de NUMERIC para INT, a consulta leva apenas cerca de 1,8 segundos.
- Selecionar tipos de dados com um comprimento curto
Tipos de dados com comprimento curto reduzem tanto o tamanho do arquivo de dados quanto a memória usada para computação, melhorando o desempenho de I/O e computação. Por exemplo, use SMALLINT em vez de INT e INT em vez deBIGINT.
- Mesmo tipo de dados para uma junção
É aconselhável usar o mesmo tipo de dados para uma junção. Para unir colunas com diferentes tipos de dados, o banco de dados precisa convertê-las para o mesmo tipo, o que leva a sobrecargas de desempenho adicionais.
Uso do índice
- O objetivo da criação de índices é acelerar as consultas. Portanto, certifique-se de que os índices possam ser usados em algumas consultas. Se um índice não for usado por nenhuma instrução de consulta, o índice não terá sentido. Exclua o índice.
- Não crie índices secundários desnecessários. Índices secundários úteis podem acelerar a consulta. No entanto, o espaço ocupado pelos índices aumenta com o número de índices. Cada vez que um índice é adicionado, um par chave-valor adicional precisa ser adicionado quando um dado é inserido. Portanto, quanto mais índices, mais lenta a velocidade de gravação e maior o uso de espaço. Além disso, muitos índices afetam o tempo de execução do otimizador e índices inadequados enganam o otimizador. Portanto, quanto mais índices, melhor.
- Crie índices adequados com base nas características do serviço. Em princípio, os índices precisam ser criados para colunas necessárias em uma consulta para melhorar o desempenho. Os índices podem ser criados nos seguintes cenários:
- Para colunas com alta diferenciação, os índices podem reduzir significativamente o número de linhas após a filtragem. Por exemplo, é aconselhável criar um índice na coluna número do cartão de identificação, mas não na coluna do gênero.
- Se houver várias condições de consulta, você poderá selecionar um índice de combinação. Observe que a coluna da condição equivalente deve ser colocada antes do índice de combinação. Por exemplo, se a consulta comum for SELECT * FROM t onde c1 = 10 e c2 = 100 e c3 > 10, você pode criar o índice de combinação Index cidx (c1, c2, c3). Dessa forma, você pode usar as condições de consulta para construir um prefixo de índice para varredura.
- Quando uma coluna de índice é usada como uma condição de consulta, não execute cálculo, função ou conversão de tipo na coluna de índice. Caso contrário, o otimizador não poderá usar o índice.
- Certifique-se de que a coluna de índice contém a coluna de consulta. Não execute sempre a instrução SELECT * para consultar todas as colunas.
- A condição de consulta é usada. =. Quando NOT IN é usado, índices não podem ser usados.
- Quando LIKE é usado, se a condição começar com o caractere curinga %, o índice não poderá ser usado.
- Se vários índices estiverem disponíveis para uma condição de consulta, mas você souber qual índice é o ideal, é aconselhável usar a dica do otimizador para forçar o otimizador a usar o índice. Isso impede que o otimizador selecione um índice incorreto devido a estatísticas imprecisas ou outros problemas.
- Quando a expressão IN é usada como a condição de consulta, o número de condições correspondentes não deve ser muito grande. Caso contrário, a eficiência de execução é baixa.