A pesquisa de índice seria visivelmente mais rápida com char vs varchar quando todos os valores fossem 36 caracteres

30

Eu tenho um esquema legado (isenção de responsabilidade!) Que usa um ID gerado com base em hash para a chave primária de todas as tabelas (existem muitas). Um exemplo dessa identificação é:

922475bb-ad93-43ee-9487-d2671b886479

Não há esperança possível de mudar essa abordagem, no entanto, o desempenho com acesso ao índice é ruim. Deixando de lado a miríade de razões isso pode ser, há uma coisa que eu notei que parecia abaixo do ideal - apesar de todos os valores de ID em todas as muitas mesas sendo exatamente 36 caracteres de comprimento, o tipo de coluna é varchar(36), não char(36) .

Alterar os tipos de coluna para comprimento fixo char(36)ofereceria benefícios significativos no desempenho do índice, além do pequeno aumento no número de entradas por página de índice, etc.?

Ou seja, o postgres tem um desempenho muito mais rápido ao lidar com tipos de comprimento fixo do que com tipos de comprimento variável?

Não mencione a minúscula economia de armazenamento - isso não será importante em comparação com a cirurgia necessária para fazer a alteração nas colunas.

boêmio
fonte

Respostas:

40

Não . Nenhum ganho . O manual declara explicitamente :

Dica: Não há diferença de desempenho entre esses três tipos , além do aumento do espaço de armazenamento ao usar o tipo preenchido em branco e alguns ciclos extras de CPU para verificar o comprimento ao armazenar em uma coluna com restrição de comprimento. Embora character(n)tenha vantagens de desempenho em outros sistemas de banco de dados, não existe essa vantagem no PostgreSQL; de fato, character(n)geralmente é o mais lento dos três por causa de seus custos adicionais de armazenamento. Na maioria das situações, text ou character varyingdeve ser usado em seu lugar .

Negrito ênfase minha.

char(n)é um tipo amplamente desatualizado e inútil. Ficar com varchar(n). Se você não precisa impor o comprimento, varcharou textseria um pouco mais rápido. Você não será capaz de medir a diferença.

Além disso, se todas as seqüências tiverem exatamente 36 caracteres, não haverá armazenamento salvando de qualquer maneira, nem mesmo uma minúscula. Ambos têm exatamente o mesmo tamanho no disco e na RAM. Você pode testar com pg_column_size()(em uma expressão e em uma coluna da tabela).

Relacionado:

Você não pediu outras opções , mas mencionarei duas:

  1. COLLATION- a menos que você esteja executando seu banco de dados com o agrupamento "C" . O agrupamento geralmente é esquecido e possivelmente caro. Como suas strings não parecem ter significado em uma linguagem natural, provavelmente não há sentido em seguir COLLATIONregras. Relacionado:

    Referência abrangente comparando (entre outros) o efeito do COLLATE "C"desempenho:

  2. UUID , obviamente. Sua string se parece com um UUID (32 dígitos hexadecimais mais 4 delimitadores). Seria muito mais eficiente armazená-los comouuidtipo de dadosreal, que é mais rápido de várias maneiras e ocupa apenas 16 bytes - em oposição a 37 bytes de RAM para umchar(36)ououtrovarchar(36)(armazenado sem delimitadores, apenas os 32 caracteres de definição) ou 33 bytes no disco. Mas o preenchimento do alinhamento resultaria em 40 bytes de qualquer maneira em muitos casos.)TambémCOLLATIONseria irrelevante para ouuidtipo de dados.

    SELECT '922475bb-ad93-43ee-9487-d2671b886479'::uuid

    Isso pode ser útil (últimos capítulos):

    Veja também:

Erwin Brandstetter
fonte
isso significa que um char / varchar (n) de comprimento restrito gastará ciclos de CPU na verificação da restrição, enquanto o campo de texto de tamanho variável armazenaria o texto separadamente de uma maneira menos acessível em comparação com char, que vence neste cenário e é essa vitória ainda vale a pena considerar para dizer 10 milhões de linhas com um pedaço de texto
PirateApp
11
@ PirateApp: char(n)quase nunca vence em nenhum aspecto. Não use. Os tipos de dados texte varchar(sem modificador de comprimento) são compatíveis com binários e compartilham as mesmas características de desempenho. Existem razões históricas para que ambos coexistam no Postgres. Internamente, texté o tipo "preferido" entre os tipos de sequência (que podem influenciar a resolução do tipo de função). Os ciclos de CPU para impor varchar(n)pouca matéria. Use uma restrição de comprimento quando precisar . No caso em questão uuidé o verdadeiro vencedor.
Erwin Brandstetter