Unlock a world of possibilities! Login now and discover the exclusive benefits awaiting you.
Olá pessoal,
É uma recomendação que as suas chaves (campos que ligam as tabelas) sejam sempre numéricas para otimizar o uso de memória.
Várias vezes recorremos ao uso da função Autonumber() e suas "primas" AutonumberHash128() e Autonumber256() para converter uma chave string para uma chave numérica.
Se você quiser ler o que diz a documentação dessas funções
Você pode notar que todas as três retornam um inteiro sequencial, baseado na ordem que seus parâmetros. A diferença entre elas é que as AutonumberHash128() e Autonumber256() calculam antes um "hash" (Wikipedia) .
Existe um "trade-off" nessa estratégia, qualquer uma delas gasta um tempo para executar o pseudo-algoritmo abaixo
- Esse parâmetro já foi carregado?
- Se sim, retorna o sequencial calculado anteriormente
- Se não, incrementa o sequencial e armazena
É usual encontrar situações em que a presença de um "autonumber" (qualquer um dos três) adicione até 20% no tempo de carga dos dados. Usualmente aceita-se esse tempo em troca da economia de memória da aplicação final.
Mas ai vem uma pergunta:
"Sei que essas funções geram uma lentidão, mas qual devo usar?"
Resolvi fazer alguns testes para comparar a velocidade de cada um deles.
Obs.:Eu foquei na geração de chaves compostas (mais de um campo) pelo fato que usualmente é o que precisamos quando montamos nossas tabelas, link-tables, etc
Para chaves compostas, a função Autonumber() tem uma pequena diferença em relação as outras duas.
A sintaxe dela é:
autonumber(expression[ , AutoID]) -- Esse AutoID é qual tabela de incrementos ela vai usar, podendo reiniciar de acordo com ela
Se eu precisar de uma chave composta, eu preciso concatenar com & os parâmetros
RegionSales:
LOAD *,
AutoNumber(Region&Year&Month) as RYMkey; // <-- Preciso concatenar com &
LOAD * INLINE [
Region, Year, Month, Sales
North, 2014, May, 245
North, 2014, May, 347
North, 2014, June, 127
South, 2014, June, 645
South, 2013, May, 367
South, 2013, May, 221];
As outras duas é:
autonumberhash128(expression {, expression}) -- Posso passar uma lista de parâmetros, sem precisar concatenar
RegionSales:
LOAD *,
AutoNumberHash128(Region, Year, Month) as RYMkey; // <-- Não preciso concatenar com &
LOAD * INLINE [
Region, Year, Month, Sales
North, 2014, May, 245
North, 2014, May, 347
North, 2014, June, 127
South, 2014, June, 645
South, 2013, May, 367
South, 2013, May, 221];
Esse "esforço" de concatenar quando usamos a autonumber() aparentemente impacta o desempenho.
Abaixo o script que usei, onde gero uma massa com 10 milhões de registros, gerando o sequencial e salvando o cronômetro
Let quant = 10000000;
Let v1=now();
t1:
LOAD
ID,
AutoNumber(ID&Valor);
load
RecNo() as ID,
Rand() as Valor
autogenerate $(quant);
Let v2=now();
t2:
LOAD
ID,
AutoNumberHash128(ID,Valor);
load
RecNo() as ID,
Rand() as Valor
autogenerate $(quant);
Let v3=now();
t3:
LOAD
ID,
AutoNumberHash256(ID,Valor);
load
RecNo() as ID,
Rand() as Valor
autogenerate $(quant);
Let v4=now();
drop Table t1,t2,t3;
Depois fiz uma pequena aplicação comparando os dados
v2-v1 | v3-v2 | v4-v3 |
---|---|---|
00:01:13 | 00:00:26 | 00:00:24 |
Podemos notar que as AutonumberHas128() e AutonumberHash256() praticamente se equivalem, mas são bem mais rápidas que a Autonumber(). Muito provavelmente isso deve-se à necessidade de concatenar as strings utilizando-se o &.
Eu acredito que esses resultados irão variar conforme a frequência de repetição, tamanho dos campos entre outras fatores.
Faça seus testes e comente aqui a que resultado
Ótimo post para a galera,
Abraço.
Muito bom! conteúdo direto e bastante agregador.
Em aplicações parrudas e com atualizações em intervalos pequenos, essas dicas fazem toda diferença.
Abraços
O campo com Hash não irá ocupar muito mais espaço na memória do que um número inteiro? O propósito não era reduzir o peso na memória?
Se você usar o AutoNumberHash*() ele vai retornar sempre um inteiro, a diferença é que ele faz um hash dos valores antes
AutonumberHash256() <=> AutoNumber(Hash256())
Sim, entendi a diferença. Obrigado! Vou testar o AutoNumber(Hash256())
Excelente post. Parabéns!