PostgreSQL - combinar colunas de várias tabelas, sem join

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

PostgreSQL - combinar colunas de várias tabelas, sem join

duartecarreira
Boas pessoal.

Estou a tentar criar uma query de monitorização. Quero juntar vários indicadores numa só tabela.

Por exemplo, usando 1 coluna de 2 tabelas:

-- calculates the uptime of the database in seconds
SELECT (now() - pg_postmaster_start_time()) as uptime,
-- cachehitration
round(sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)),5)*100 as cachehitratio
FROM pg_stat_activity, pg_statio_user_tables;

Funciona às 1000 maravilhas:
uptime                         cachehitratio
24 days 03:14:01.094   99.76300

Mas assim que começo a pedir várias colunas da 1ª tabela isto baralha-se. Nos docs diz que quando temos várias tabelas no FROM é feito um cross-join o que me parece bem. Mas pode ser o problema?
(http://www.postgresql.org/docs/9.2/static/queries-table-expressions.html)

Um exemplo deste problema:
-- 1) calculates the uptime of the database in seconds
SELECT (now() - pg_postmaster_start_time()) as uptime,
-- 2) número de conexões, da mesma tabela que 1)
COUNT(pg_stat_activity.*) as conexoes,
-- 3) cachehitratio
round(sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)),5)*100 as cachehitratio
FROM pg_stat_activity, pg_statio_user_tables;

O resultado não é correcto para a coluna #2, conexões:
uptime                       conexoes  cachehitratio
24 days 03:19:22.73   360         99.76300

Só tenho 6 registos na tabela pg_stat_activity, não 360...


Outra abordagem que tentei foi usar o UNION, e obter todos os resultados numa só coluna, o que obriga a ter sempre o mesmo tipo de resultado: int, texto, tempo, etc. para ser universal tenho de converter para texto o que elimina a utilidade da monitorização...

Por exemplo:
SELECT (now() - pg_postmaster_start_time())::text as valor, 'uptime' as nome FROM pg_statio_user_tables
UNION
select count(*)::text as valor, 'conexões' as nome from pg_stat_activity;

O resultado que dá é:
valor                           nome
6                                conexoes
24 days 03:24:26.914  uptime

O problema aqui é limitar-nos a um só tipo de valores.

Agora a pergunta: têm sugestões para isto? Há outra abordagem?

Abraços,
Duarte
Reply | Threaded
Open this post in threaded view
|

Re: PostgreSQL - combinar colunas de várias tabelas, sem join

Giovanni Manghi-2
> Um exemplo deste problema:
> -- 1) calculates the uptime of the database in seconds
> SELECT (now() - pg_postmaster_start_time()) as uptime,
> -- 2) número de conexões, da mesma tabela que 1)
> COUNT(pg_stat_activity.*) as conexoes,
> -- 3) cachehitratio
> round(sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)),5)*100
> as cachehitratio
> FROM pg_stat_activity, pg_statio_user_tables;
>
> O resultado não é correcto para a coluna #2, conexões:
> uptime                       conexoes  cachehitratio
> 24 days 03:19:22.73   360         99.76300
>
> Só tenho 6 registos na tabela pg_stat_activity, não 360...


eu não sei se percebi bem o problema, mas parece-me que sem um (exemplo)

WHERE
id.pg_stat_activity = id.pg_statio_user_tables

vai dar problemas porque se os records nas 2 tabelas não são
relacionados ele faz (exemplo com 2 registos em cada tabela):

tabela1_registro1 tabela2_registro1
tabela1_registro2 tabela2_registro1
tabela1_registro1 tabela2_registro2
tabela1_registro2 tabela2_registro2
_______________________________________________
Portugal mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/portugal
Reply | Threaded
Open this post in threaded view
|

Re: PostgreSQL - combinar colunas de várias tabelas, sem join

duartecarreira
Giovanni, a mim resulta apenas 1 registo de cada tabela, embora os docs digam realmente que é feito um cross-join, como indicas.

O problema é que com 3 colunas de 2 tabelas, os dados devolvidos não são correctos (conexões = 360).

Mas ontem o Fred Lehodey mandou-me uma solução alternativa que é fazer sub-queries:

Select * from
(
SELECT (now() - pg_postmaster_start_time())::text as valor, 'uptime' as nome
FROM pg_statio_user_tables
) as foo
,
(select count(*)::text as valor, 'conexões' as nome from pg_stat_activity
) as foo2

O que deve resultar. Ter uma subquery por indicador.

Abraço e obrigado. Isto é soluções em tempo recorde, mais uma vez.
Duarte