Esta página foi traduzida por máquina. Leia o original em inglês. English

Biblioteca IBSurgeon

As diferenças entre campos VARCHAR e INTEGER em chaves

Estou usando IDs inteiros como chaves primárias nas minhas tabelas. E se eu usasse campos varchar? Vou perder desempenho nesse caso, especialmente para tabelas grandes? As junções (joins) ainda funcionarão tão rápido quanto funcionam com a coluna inteira?

Seu desempenho deve ser praticamente o mesmo com varchars ou inteiros. O Firebird sempre compara chaves de índice byte a byte e apenas a parte significativa do valor é armazenada.

Uma chave de campo único é primeiro convertida para um dos três tipos canônicos: string com collation, double precision e (infelizmente) inteiro de 64 bits. Datas se tornam números de ponto flutuante double precision.

Strings que têm uma collation diferente do seu valor de byte são convertidas para o formato da collation. Isso é algo como uma arte negra e expande o tamanho da string, mas o resultado é que a string encontra seu lugar correto quando ordenada com outras strings da mesma collation. ‘A’, ‘a’, ‘â’, ‘á’, ‘Ă’, ‘ã’, ‘ä’, ‘å’, ‘ă’, ‘ą’, ‘Ā’ aparecem todos em seus devidos lugares. (Desculpe pelo que isso fez com seu cliente de e-mail… no meu, são onze variantes de ‘A’.) Espaços finais não são incluídos na chave.

O número double precision é embaralhado para que também seja ordenado byte a byte - aproximadamente invertendo o sinal, depois o expoente, depois a mantissa, truncando zeros finais.

Dependendo da endianness dos inteiros de 64 bits no computador, eles também são embaralhados para que sejam comparados byte a byte. Isso pode parecer uma desotimização, mas as chaves de índice não são armazenadas em limites naturais e passam por compressão de prefixo, então não há como usar uma comparação maior do que byte a byte.

Chaves compostas são praticamente iguais. Cada parte é convertida para seu tipo de chave de índice e preenchida até um múltiplo de 4 bytes. Após cada quatro bytes, o Firebird adiciona um byte com a posição do campo atual da chave. Assim, um índice em Sobrenome, Nome, SignoZodiacal resultaria em 1Harr1ison2Ann 3Gemi3ni. Isso evita o constrangimento de confundir “Damnation” com “Dam nation”.

Por que eu disse “(infelizmente)” acima? Porque ter um formato único para números permite que o Firebird mude o tamanho dos números sem recriar os índices sobre eles. Mas quando a Borland adicionou inteiros de 64 bits de volta - o InterBase tinha inteiros de 64 bits desde o início nos Vaxes - alguma mente brilhante percebeu que double precision tem 56 bits de precisão e inteiros de 64 bits têm 64 bits. Por outro lado, os índices do Firebird são projetados para lidar com alguma imprecisão… ou os 8 bits restantes poderiam ser anexados ao final… tanto faz. Então você precisa reconstruir índices ao passar de Numeric/Decimal 9 para Numeric/Decimal 12. Triste.

“Compressão de prefixo?” Ao armazenar uma chave que não seja a primeira em uma página ou a primeira após um salto na página, o Firebird analisa a chave anterior e trunca a parte do início da próxima chave que duplica sua antecessora e anexa o comprimento da parte truncada no início. Assim, as strings “AAAA”, “AAAB”, “AAAC”, “AABC” se tornam

“AAAA”, “3B”, “3C” e “2BC”. Há um problema com alguns formatos de GUID que colocam a parte volátil do número primeiro, seguida pela parte fixa. Isso prejudica a compressão de prefixo e infla o tamanho dos índices.

“Salto?” - A compressão de prefixo reduz bastante o tamanho dos índices, diminuindo a E/S, mas exige leitura de toda a página para decifrar a chave. Tudo bem com páginas de 1K, mas com tamanhos de página maiores o cálculo se tornava inaceitável. Então cada página de índice agora tem um índice próprio apontando para os offsets das entradas não comprimidas. Esse índice é chamado de vetor de salto.

Ann Harrision