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

Responder a