AE    
Por A. Elein Mustain
Traduzidos por Juliano da Silva Ignacio
General Bits 26-May-2003 Issue: 27

General Bits é uma coluna baseada na lista de discussão pgsql-general do PostgreSQL.
Para maiores informações sobre a lista pgsql-general e o PostgreSQL, veja www.PostgreSQL.org.
Arquivos
General Tidbits
Artigos em Português
Google General Bits
Notícias
Para receber notícias sobre as novas edições do General Bits via email, envie um email para Elein.
ae Consulting PostgreSQL Design & Implementation
Assinaturas Support General Bits
pghostger.com
Palestrante da OSCON
 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

New Portuguese Articles
Novos Artigos em Português 24/Mai/2003

There is another new link on PostgreSQL General Bits for Portugues speakers. In contains articles from General Bits translated by Juliano da Silva Ignacio. Welcome to Portugues readers. I'm sure you will enjoy Juliano's work.

Há um novo link no General Bits do PostgreSQL para o idioma Português. Nele estão contidos artigos do General Bits traduzidos por Juliano da Silva Ignacio. Bem vindos leitores da Língua Portuguesa. Eu tenho certeza que o trabalho feito por Juliano irá agradá-los.

Este edição é o primeiro de uma série PostgreSQL General Bits Edição: 26

Colaboradores: Juliano S. Ignacio jsignacio em hotmail.com, elein em varlena.com

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Conflitos com Nomes de Variáveis
[GENERAL] PLPGSQL Buscando registros 20/Mai/2003

Quando uma boa função em pl/pgsql é criada, tenha certeza de que as variáveis declaradas não tenham os mesmos nomes que os nomes de colunas ou tabelas utilizadas na função. Variáveis utilizadas em funções escritas em pl/pgsql terão precedência sobre o nome de colunas ou tabelas e, nem sempre é esta a intenção. O que deveria também ser notado, enquanto estamos neste assunto, é que também não se deve usar palavras chaves do SQL como nomes de variáveis, mas você já deve saber disso, não é mesmo?

É particularmente importante revisar os nomes das variáveis atrás de conflitos se uma função em pl/pgsql não está se comportando como deveria se comportar. Um exemplo disto está na função abaixo, que tem a variável project_code declarada e depois, numa consulta dentro da função, retorna a coluna (com mesmo nome) project_code de uma tabela.

CREATE FUNCTION UpdateNextProjectCode() RETURNS OPAQUE AS '
DECLARE
	project_code          INTEGER;
	...
BEGIN
	...
	OPEN used_project_codes 
		FOR SELECT project_code FROM projects 
		WHERE project_code > 0 ORDER BY project_code ASC;
	...
A variável project_code ainda não foi inicializada no pl/pgsql, portanto seu valor é NULL. As variáveis em pl/pgsql são expandidas (tem seu conteúdo utilizado) antes de uma consulta ser executada, então, a instrução abaixo foi, o que foi executado (oops):
	SELECT NULL 
	FROM projects 
	WHERE NULL > 0 
	ORDER BY NULL ASC;
Isso provavelmente não era o que se pretendia originalmente.

O problema de conflito de nomes no pl/pgsql é muito comum, portanto, adicione-o à sua lista de verificação quando estiver testando e 'debugando' funções no servidor.

Colaboradores: Mark Nelson mn em tardis.cx, Tom Lane tgl em sss.pgh.pa.us

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Tamanho de Tabelas e Performance
[GENERAL] Dúvida sobre a capacidade do PostgreSQL 03/Abr/2003

O tamanho de uma tabela não tem muita importância com relação à performance quando se trata de um servidor bem configurado e com indexação coerente. Algumas dezenas, não, digo, centenas de milhares de registros é um tamanho perfeitamente razoável para uma tabela e muitos ainda irão achar que é pequena.

Um questionamento sobre portar uma tabela de 95000 registros trouxe à tona os seguintes depoimentos e precauções:

Eu tenho uma quantidade de 1.000.000 ou mais de registros por tabela (muito mais em alguns casos) rodando em máquinas simples de poucos recursos (Celerons com HDs IDE de 5400rpm, Netras) e performance perfeitamente adequada para o uso típico. -- Steve
Quase ridiculamente pequeno :) Sim, aquelas buscas por índices sequenciais e tsearch poderão matar uma aplicação, mas as consultas de seleção irão voar. -- Nigel
Você está absolutamente correto sobre haver muitos outros fatores que determinam a performance por parte da contagem de registros. Tendo dito isto, tenho tabelas com mais de um milhão de entradas em sistemas de uso contínuo que mostram um ótimo desempenho utilizando consultas e índices, e também muito aceitável em consultas que requerem uma busca seqüencial. -- Ryan
Se as consultas são de seleção e tipicamente indexadas, ou você tem possui RAM suficiente, ou - como então eu diria - não haveria muita diferença entre dividir tabelas ou combiná-las em apenas uma.

Uma tabela com 95000 registros poderia ser considerada pequena. Você deve sempre ter RAM suficiente para colocar em cache todo o BD - pode estimar pelos indícios de uso do disco pelo BD. --Link

Nós utilizamos o PostgreSQL para muitas coisas que possuem mais do que 90.000 registros. Nós temos uma tabela que usamos para juntar arquivos log de múltiplos servidores e então classificá-los cronologicamente.

O tamanho desta tabela no disco rígido é 226.689.024 bytes. E é uma das menores tabelas em que trabalhamos neste servidor. Por favor, note que este é o nosso servidor em produção, muito bem configurado. Uma estação de trabalho que possui configuração padrão e menos memória pode não ser tão rápido quanto, mas você ainda estará obtendo respostas abaixo de um segundo em conjuntos de dados bem indexados com 5.000.000 de registros ou perto disto. --Scott

Colaboradores: John Wells jb em sourceillustrated.com, Steve Atkins steve em blighty.com, Nigel J. Andrews nandrews em investsystems.co.uk, Ryan Mahoney ryan em paymentalliance.net, Lincoln Yeoh lyeoh em pop.jaring.my, scott.marlowe scott.marlowe em ihs.com
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Guardando em Cache o Resultado de Consultas
[GENERAL] guardando em cache o resultado de consultas 21/Mai/2003

Especialmente em consultas lentas, isto ajuda na capacidade de armazenar o conjunto de dados resultante e reusá-lo novamente (se necessário). Isto pode ser um pouco complicado se sua aplicação é uma aplicação para internet. Neste caso, é importante saber o escopo no qual voce quer manter seu conjunto de resultados. Por transação? Por conexão? Por sessão?

O meio "usual" para guardar em cache o resultado de consultas é utilizando CURSORes:

	BEGIN;
	DECLARE cursorname FOR query;
	FETCH number_of_rows FROM cursorname;
	MOVE {FORWARD|BACKWARD} number_of_rows IN cursorname;
	...
	COMMIT;
Este método tem um problema quando se trabalha através de transações e conexões. Usando conexões conjuntas persistentes (persistant pooled connections) às vezes parece ser uma boa opção, mas às vezes o benefício da performance não vale o esforço despendido. Scott Marlow escreve,
"Conexões persistentes são, geralmente 1000 vezes (ou mais) mais rápido do que estabelecer conexões não-persistentes, mas quando conexões não-persistentes conectam em apenas uma fração de segundo (1/10.000), não representa um grande ganho de velocidade possuir conexões persistentes."
Utilizando conexões persistentes é de boa prática confirmar (COMMIT) ou desfazer (ROLLBACK) uma transação antes de liberar a conexão do poll (conjunto) porque é difícil manter uma transação através de conexões conjuntas (pooled connections). O acompanhamento (tracking) da sessão é necessário, assim como, a coordenação de todas as sessões com suas respectivas conexões. Muitos utilitários de conexão conjunta (connection pooling) não se conformam com estes requerimentos.

Exige-se que os cursores estejam dentro de uma transação, dessa maneira seus benefícios estão limitados pelo escopo da mesma. Isto cuida da rejeição de conexões conjuntas (connection pools) com cursores, como uma solução para quando você quiser um cursor para a última sessão.

A outra maneira "usual" é guardar em cache os dados de uma aplicação cliente em estruturas que estejam disponíveis. Isto é muito comum, ainda que o benefício da disponibilidade, armazenamento e manipulação devam ser comparados ao custo de executar novamente a consulta.

Uma tabela temporaria para armazenar a informação consultada não funcionará porque irá desaparecer quando a conexão for fechada. Manipulando cuidadosamente os cursores podem funcionar com conexões conjuntas (connection pooling). A alternativa é uma simples tabela de resultados. Algumas considerações teriam que ser feitas para coletar o lixo da "simples" tabela temporaria, dependendo do escopo desejado do conjunto de dados.

Colaboradores: alex b. mailinglists1 em gmx.de, scott.marlowe scott.marlowe em ihs.com, Darko Prenosil darko.prenosil em finteh.hr, Nigel J. Andrews nandrews em investsystems.co.uk

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Sintaxe de SELECT DISTINCT ON
[GENERAL] Erro no SELECT DISTINCT ON? 20/Mai/2003

A sintaxe para DISTINCT é facilmente mal interpretada. Aqui está uma definição normal:

	SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
	* | expression [ AS output_name ] [, ...]

Isto é fácil de escrever:

	SELECT DISTINCT ON (dai_genres.id), dsc FROM dai_genres
quando você realmente sabe o que significa
	SELECT DISTINCT ON (dai_genres.id) dsc FROM dai_genres
Tire fora a vírgula após o parêntesis. A cláusula DISTINCT está antes e separada da lista de destino (colunas de resultado). A coluna usada na cláusula DISTINCT não está inclusa na lista de destino a menos que você a inclua especificamente pelo nome ou implicitamente a inclua com um *.
	SELECT DISTINCT ON (dai_genres.id) * FROM dai_genres

Foi discutido se a sintaxe deveria ter tido colchetes em volta da lista de destino. Isto foi sugerido para separar as cláusulas opcionais DISTINCT ou ALL da lista de destino. Mas, não estou convencido; e novamente ninguém me questionou :-)

Foi também colocado de fora a parte do OR (operador alternativo) na lista de destino:

	* | expression [ AS output_name ] [, ...] 
que apontava que você não poderia fazer SELECT *, oid FROM ... o qual todos nós sabemos, é uma lista de destino válida.

Isto é o que o SQL Spec diz sobre os simbolos:

3.2 Notação
[ ] Colchetes indicam elementos opcionais na fórmula. A parte da fórmula contida nos colchetes deve ser explicitamente especificada ou deve ser omitida.
{ } Chaves agrupam os elementos na fórmula. A parte da fórmula contida nas chaves deve ser explicitamente especificada.
| O operador alternativo. A barra vertical indica que a parte da fórmula seguinte à barra é uma alternativa para a parte que precede a mesma barra. Se a barra vertical aparece numa posição onde não está contida em chaves ou colchetes, ela especifica uma alternativa completa para um elemento definido pela regra de produção. Se a barra vertical aparece entre chaves ou colchetes, isto especifica alternativas para o conteúdo do mais interno par de chaves ou colchetes.
Nós nos importamos muito com a sintaxe como uma ponte entre o nosso entendimento e o entendimento do computador. Discussões sobre particularidades da sintaxe ajudam-nos a criar uma maneira fácil e legível de entender o modo de expressar as instruções.

Colaboradores: Jean-Christian Imbeault jc em mega-bucks.co.jp, Martijn van Oosterhout kleptog em svana.org, Nigel J. Andrews nandrews em investsystems.co.uk, Bruno Wolff III bruno em wolff.to, scott.marlowe scott.marlowe em ihs.com

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Percorrendo um Vetor
[GENERAL] Pl/PgSql: Loop em um Array 22/Mai/2003

Uma dúvida sobre como percorrer (loop) um vetor (array) trouxe um belo exemplo de como fazer isso exatamente (por Joe Conway). Este exemplo necessita a versão 7.3. Para funções similares, veja também Ediçao 24 Artigo 6 .

	CREATE OR REPLACE FUNCTION atest(INT[]) RETURNS TEXT AS '
	DECLARE
	   mya alias for $1;
	   myret text = '''';
	   low int;
	   high int;
	BEGIN
	   low  := replace(split_part(array_dims(mya),'':'',1),''['','''')::int;
	   high := replace(split_part(array_dims(mya),'':'',2),'']'','''')::int;
	
	   FOR i IN low..high LOOP
	     myret := myret || ''|'' || mya[i];
	   END LOOP;
	
	   RETURN myret;
	END;
	' LANGUAGE 'plpgsql' IMMUTABLE STRICT;
	
	regression=# select atest('{1,2,3,4}'::int[]);
	   atest
	----------
	  |1|2|3|4
	(1 row)
	

Colaboradores: Axel Straschil axel em pizza.home.kosnet.com, Joe Conway mail em joeconway.com


Comentários e Correções são bem vindos. Sugestões e contribuições de itens também são bem vindos. Envie-os!.
Copyright A. Elein Mustain 2003

Google
Search General Bits & varlena.com Search WWW