William Leite Araújo wrote: > Ok. Vamos lá. Faça um teste Euler. Execute /*SELECT* * *FROM* > [tabela]* WHERE *[tabela].[chave] = '1.0'::NUMERIC;/
Sei que era para o Euler fazer o teste mas eu não resisti. Para começar, que cast mais desnecessário é este que fizestes?? Não seria mais simples e inteligente algo como: "select * from tabela where chave = 1.0;" > De preferência em uma tabela onde hajam mais de 1000 registros. Em > seguida, execute a mesma consulta, mas comparando com um inteiro. Como você informa 1000 registros eu criei uma tabela com 50000 para que ficasse mais claro esta gritante diferença que o terrível numeric causaria nas minhas consultas. É claro que eu também me preparei com uma garrafa de café para passar a noite aqui esperando o retorno delas e também já avisei minha namorada que eu não iria para casa tão cedo. Criei a tabela assim: novo=# create table tablefoo(anytext varchar(100), valor numeric(6,3));; CREATE TABLE novo=# create index tablefoo_idx1 on tablefoo(valor); CREATE INDEX E gerei os 50000 valores aleatórios com um pequeno script em php assim: <?php include "../inc/class/Conexao.inc"; $db = new Conexao(); $db->beginTransaction(); for($i = 0; $i <= 50000; $i++){ $foo = mt_rand(0,10); $bar = mt_rand(0,999); $sql = "insert into tablefoo(anytext, valor) values('iteration $i', $foo.$bar);"; $db->query($sql); } $db->commit(); ?> > Oh.... é muuuuuuuuuuuuito mais lenta. Porquê? A (excelente) > documentação explica: Para verificar os tempos de resposta eu ativei o timing novo=# \timing Timing is on. Avisei a todos no meu icq e gtalk que eu ficaria off por cerca de 20h para alguns testes de performance na minha máquina. novo=# select * from tablefoo where valor = 1.345; anytext | valor -----------------+------- iteration 9094 | 1.345 iteration 10389 | 1.345 iteration 42065 | 1.345 (3 rows) Time: 0.470 ms novo=# select * from tablefoo where valor = '1.345'::numeric; anytext | valor -----------------+------- iteration 9094 | 1.345 iteration 10389 | 1.345 iteration 42065 | 1.345 (3 rows) Time: 0.477 ms novo=# Realmente seu casting deixou minha consulta 7 milhonésimos de segundo mais lenta. Vamos ver casting para float para ter certeza que ele é lento, parece que não vai dar tempo nem para tomar um café, quanto mais a garrafa que eu preparei: novo=# select * from tablefoo where valor = '1.345'::float; anytext | valor -----------------+------- iteration 9094 | 1.345 iteration 10389 | 1.345 iteration 42065 | 1.345 (3 rows) Time: 90.041 ms Agora já temos uma enorme diferença, 90 milésimos de segundo. Vamos pegar a parte inteira de todos os 50000 registros para ver se eu consigo demorar mais tempo, pelo menos até tomar uma dose de café. novo=# \o lixo.txt novo=# select anytext, round(valor) from tablefoo; Time: 90.500 ms Poxa, 90 milésimos de segundo para arredondar 50000 registros numéric. Então vamos tentar converter para o tipo varchar novo=# select anytext, valor::varchar from tablefoo; Time: 109.672 ms Retirar somente a parte inteira dos 50000 registros; novo=# select anytext, trunc(valor) from tablefoo; Time: 129.208 ms Desisto, não vou ter tempo nem para tomar um cafezinho. O PostgreSql insiste em tratar os 50000 registros com dados numeric em menos de um décimo de segundo. > Ainda sem fundamento? Sinto muito cara, mas infelizmente sim. > Para compor um único registro eram feitas em torno de 10 consultas > dessa forma, além das 2 consultas de auto-referência (na mesma tabela > haviam, eventualmente, o "pai" e a "mãe" do mesmo). Como eu disse, limitação do ambiente, da tecnologia, do seu script de migração, de falta de modelagem, de qualquer outra coisa que você sonhar no mundo, menos do PostGreSql. Portanto eu peço que não envie mensagens com afirmações infundadas e distorcidas para o grupo pois pode prejudicar quem está começando agora no PostGreSql. > Assim, os 378,998 registros, sem o cuidado de usar um cast para tipo > inteiro (primeira versão da função) demorou em torno de 20 horas. Após a > otimização foram menos de 2 minutos. > > Infelizmente não posso lhe mostrar os dados, mas GARANTO que, tanto > num 8.2 quanto num 8.3, você poderá experimentar a diferença no tempo > simplesmente comparando uma constante numeric com uma constante integer. Opa, isto eu não tinha tentado ainda, vamos lá; novo=# select * from tablefoo where valor = 1; anytext | valor -----------------+------- iteration 21263 | 1.000 iteration 34970 | 1.000 iteration 37109 | 1.000 iteration 42379 | 1.000 iteration 43073 | 1.000 (5 rows) Time: 3.568 ms Poxa, 3 milesegundos comparando com inteiros! Desisto cara, você fez mágica com sua rotina de migração. Ja liguei para minha namorada e disse que agente vai poder se ver, ela pediu para te agradecer, agora ainda estou triste por estragar uma garrafa inteira de cafezinho. Ao menos tomei um agora no final. Abraço, -- Shander Lyrio _______________________________________________ pgbr-geral mailing list pgbr-geral@listas.postgresql.org.br https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral