O tipo de dados uuid
é perfeitamente adequado para a tarefa. Ele só ocupa 16 bytes em oposição a 37 bytes de memória RAM para o varchar
ou text
representação. (Ou 33 bytes no disco, mas o número ímpar exigiria preenchimento em muitos casos para torná-lo efetivamente 40 bytes.) E o uuid
tipo tem mais algumas vantagens.
Exemplo:
SELECT md5('Store hash for long string, maybe for index?')::uuid AS md5_hash
Detalhes e mais explicações:
Você pode considerar outras funções de hash (mais baratas) se não precisar do componente criptográfico do md5, mas eu usaria o md5 para o seu caso de uso (principalmente somente leitura).
Uma palavra de advertência : Para o seu caso ( immutable once written
), uma PK funcionalmente dependente (pseudo-natural) é adequada. Mas o mesmo seria uma dor onde as atualizações text
são possíveis. Pense em corrigir um erro de digitação: o PK e todos os índices dependentes, colunas do FK dozens of other tables
e outras referências também teriam que mudar. Inchaço de tabela e índice, problemas de bloqueio, atualizações lentas, referências perdidas, ...
Se text
puder mudar na operação normal, uma PK substituta seria uma escolha melhor. Sugiro uma bigserial
coluna (intervalo -9223372036854775808 to +9223372036854775807
- são nove quintilhões duzentos e vinte e três quatrocentos trezentos e setenta e dois trilhões trinta e seis algo bilhões ) para valores distintos billions of rows
. Em qualquer caso, pode ser uma boa ideia : 8 em vez de 16 bytes para dezenas de colunas e índices do FK!). Ou um UUID aleatório para cardinalidades muito maiores ou sistemas distribuídos. Você sempre pode armazenar o md5 (as uuid
) adicionalmente para encontrar rapidamente linhas na tabela principal a partir do texto original. Relacionado:
Quanto à sua consulta :
Para abordar o comentário de @ Daniel : Se você preferir uma representação sem hífens, remova os hífens para exibição:
SELECT replace('90b7525e-84f6-4850-c2ef-b407fae3f271', '-', '')
Mas eu não me incomodaria. A representação padrão está correta. E o problema realmente não é a representação aqui.
Se outras partes devem ter uma abordagem diferente e jogar cordas sem hífens na mistura, isso também não é um problema. O Postgres aceita várias representações de texto razoáveis como entrada para a uuid
. A documentação :
O PostgreSQL também aceita as seguintes formas alternativas de entrada: uso de dígitos maiúsculos, o formato padrão entre parênteses, omitindo alguns ou todos os hífens, adicionando um hífen após qualquer grupo de quatro dígitos. Exemplos são:
A0EEBC99-9C0B-4EF8-BB6D-6BB9BD380A11
{a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11}
a0eebc999c0b4ef8bb6d6bb9bd380a11
a0ee-bc99-9c0b-4ef8-bb6d-6bb9-bd38-0a11
{a0eebc99-9c0b4ef8-bb6d6bb9-bd380a11}
Além disso, a md5()
função retorna text
, você usaria decode()
para converter bytea
e a representação padrão disso é:
SELECT decode(md5('Store hash for long string, maybe for index?'), 'hex')
\220\267R^\204\366HP\302\357\264\007\372\343\362q
Você precisaria encode()
novamente para obter a representação de texto original:
SELECT encode(my_md5_as_bytea, 'hex');
Para completar, os valores armazenados como bytea
ocupariam 20 bytes na RAM (e 17 bytes no disco, 24 com preenchimento ) devido à sobrecarga internavarlena
, o que é particularmente desfavorável para o tamanho e o desempenho de índices simples.
Tudo funciona a favor de um uuid
aqui.
text
colunas - mesmo que não seja um "texto".SELECT encode(decode('tZmffOd5Tbh8yXaVlZfRJQ==', 'base64'), 'hex')::uuid;
.uuid
é um tipo de 16 bytes que não pode armazenar os resultados de qualquer algoritmo SHA que produza entre 160 e 512 bits. Não existe um tipo semelhante que se encaixe na distribuição padrão do Postgres. Você pode criar um ... Na falta disso, o padrão ébytea
como pg_crypto .Eu armazenaria o MD5 em uma coluna
text
ouvarchar
. Não há diferença de desempenho entre os vários tipos de dados de caracteres. Você pode restringir o comprimento dos valores md5 usandovarchar(xxx)
para garantir que o valor md5 nunca exceda um determinado comprimento.As grandes listas IN geralmente não são muito rápidas, é melhor fazer algo assim:
Outra opção que às vezes se diz ser mais rápida é usar uma matriz:
Como você está apenas comparando a igualdade, um índice BTree regular deve ser bom. Ambas as consultas devem poder usar esse índice (especialmente se estiverem selecionando apenas uma pequena fração das linhas.
fonte
bit
tipo, então não posso comentar sobre isso. Dado o seu número esperado de linhas, a sugestão de Erwin parece ser melhor por causa da economia de espaço que você começa com armazenar isso como UUIDOutra opção é usar 4 colunas INTEGER ou 2 BIGINT.
fonte