Devo investir tempo para alterar o tipo de coluna de CHAR (36) para UUID?


14

Eu já tenho alguns milhões de linhas no meu banco de dados. Eu não sabia sobre o tipo de dados UUID do PostgreSQL quando projetei meu esquema.

Uma das tabelas possui 16 milhões de linhas (cerca de 3,5 milhões a 4 milhões de registros por fragmento), crescendo cerca de 500 mil registros por dia. Ainda tenho o luxo de desativar o sistema de produção por algumas horas, se necessário. Não terei esse luxo em uma ou duas semanas.

Minha pergunta é: valerá a pena fazê-lo? Estou me perguntando sobre o desempenho do JOIN, o uso do espaço em disco (o dump completo do gzip é de 1,25 GiB), coisas dessa natureza.

O esquema da tabela é:

# \d twitter_interactions
                Table "public.twitter_interactions"
         Column          |            Type             | Modifiers 
-------------------------+-----------------------------+-----------
 interaction_id          | character(36)               | not null
 status_text             | character varying(1024)     | not null
 screen_name             | character varying(40)       | not null
 twitter_user_id         | bigint                      | 
 replying_to_screen_name | character varying(40)       | 
 source                  | character varying(240)      | not null
 tweet_id                | bigint                      | not null
 created_at              | timestamp without time zone | not null
Indexes:
    "twitter_interactions_pkey" PRIMARY KEY, btree (interaction_id)
    "twitter_interactions_tweet_id_key" UNIQUE, btree (tweet_id)
    "index_twitter_interactions_on_created_at" btree (created_at)
    "index_twitter_interactions_on_screen_name" btree (screen_name)
Triggers:
    insert_twitter_interactions_trigger BEFORE INSERT ON twitter_interactions FOR EACH ROW EXECUTE PROCEDURE twitter_interactions_insert_trigger()
Number of child tables: 9 (Use \d+ to list them.)

Respostas:


13

Eu consideraria mudar para o tipo UUID. char(36)ocupa 40 bytes, uuidocupa 16, portanto, você economizará 24 bytes por linha, o que equivale a 12 MB por dia, 4 GB após um ano. Mais índices. Dependendo do hardware que você possui, isso não é muito, mas poderia ser. E isso se acrescenta se você tiver mais oportunidades de melhoria como essa.

Além disso, não vejo nenhuma restrição em seu esquema que garanta que ele interaction_idesteja realmente no formato correto. Usar o tipo certo também lhe dará isso.

Se você gosta disso, no entanto, usar bigintum economizador ainda mais e um desempenho ainda melhor. É muito improvável que seu aplicativo seja tão grande que uma bigintcoluna para um ID não funcione.


Eu tenho um sistema distribuído: várias fontes de dados geram IDs para as interações, portanto, não posso usar um BIGINT simples, a menos que tenha reservado N bits para o ID do nó.
François Beausoleil

3
@ FrançoisBeausoleil, reservar N bits para o ID do nó é igual a usar cada número enésimo em uma sequência (e, portanto, fácil de implementar). Além disso, você pode considerar o uso de chaves compostas.
razoável,

1
Coordenar várias seqüências (com ID do nó) é um problema administrativo na prática e propenso a erros humanos. Não vejo razão para não usar UUIDs nesse cenário, principalmente porque os bits são baratos hoje em dia (memória e armazenamento). De fato, esse cenário é o motivo pelo qual os UUIDs foram inventados décadas atrás: compartilhar dados entre sistemas distribuídos sem coordenação centralizada .
Basil Bourque

6

Não sou uma pessoa do postgres de maneira alguma, mas com base no que sei do SQL Server, quanto mais linhas você puder caber em uma página de dados, melhor será o desempenho (a leitura de dados do disco normalmente é operação mais cara). Assim, passar de um campo de 36 ish 1 byte para 16 bytes GUID parece uma economia de custos direta. Quanto menos leituras você conseguir, mais rápido poderá retornar resultados. Obviamente, tudo isso pressupõe que um GUID / UUID satisfaça as necessidades de negócios da tabela. Se satisfaçam UUID ele, faria um bigint ? Isso reduziria ainda mais seu armazenamento, custando mais 8 bytes por linha.

Editar 1

Para dados de caracteres no Postgres, há um custo adicional de armazenamento para eles. Seqüências curtas, com menos de 127 bytes, têm uma sobrecarga de 1 byte, enquanto qualquer outra com mais bytes possui 4 bytes, e é assim que o segundo respondente apresentou um custo de 40 bytes para um campo de 36 bytes. Mas também há uma opção para a compactação de strings, de modo que talvez não custe 40. Não sei dizer qual seria o custo final, mas os fundamentos permanecem: qualquer coisa com mais de 16 bytes aumentará o custo de armazenamento, levará mais tempo para ler e consome mais memória.

O requisito de armazenamento para uma cadeia curta (até 126 bytes) é de 1 byte mais a cadeia real, que inclui o preenchimento de espaço no caso de caractere. As cadeias mais longas têm 4 bytes de sobrecarga em vez de 1. As cadeias longas são compactadas pelo sistema automaticamente, portanto, o requisito físico no disco pode ser menor.


3

Além da questão de espaço, lembre-se de que você precisará alterar todas as tabelas para usar o tipo de dados correto, ou o desempenho da sua junção diminuirá muito.


Isso foi um dado, mas obrigado por me lembrar.
François Beausoleil

3
Ao fazer grandes mudanças como essa, acho que escrever tudo (não importa o quão simples seja lembrar) geralmente compensa.
mrdenny

3

Além da economia no tamanho de dados e índices (como dito por outros), que se traduz em economia de E / S, o que você precisa considerar é como você irá gerar novos valores interaction_ide qual será o impacto no índices e condições de consulta (junções).

Para o índice - será menor, no entanto, se muitas de suas consultas usarem varreduras de índice, alternar para UUIDs poderá tornar as varreduras de índice impossíveis (dependendo de como você gerará UUIDs) e bigintpoderá ser uma escolha muito melhor.

Por fim, como o impacto real no desempenho depende também de seus padrões de uso e distribuição de dados, você deve executar testes e ter um ambiente de desenvolvimento e teste no qual é possível testar suas alterações.

Isso fornecerá uma resposta muito mais exata sobre o impacto no desempenho.


Obrigado pela contribuição útil e bem-vindo ao site :)
Jack diz que tenta topanswers.xyz

Meus padrões de acesso são por períodos, JOIN usando o screen_name ou por UUID. Não são previstas varreduras de intervalo no ID exclusivo. Obrigado pela sua resposta, muito informativo.
François Beausoleil
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.