quinta-feira, 2 de abril de 2015

Paginando resultados com limit e offset

Neste post, veremos como utilizar o LIMIT e o OFFSET para paginar resultados de uma SQL.
A cláusula LIMIT é utilizada para limitar o número de resultados de uma SQL. Então, se sua SQL retornar 1000 linhas, mas você quer apenas as 10 primeiras, você deve executar uma instrução mais ou menos assim:
1
SELECT coluna FROM tabela LIMIT 10;
Agora, vamos supor que você quer somente os resultados de 11 a 20. Com a instrução OFFSET fica fácil, basta proceder da seguinte forma:
1
SELECT coluna FROM tabela LIMIT 10 OFFSET 10;
O comando OFFSET indica o início da leitura, e o LIMIT o máximo de registros a serem lidos. Para os registros de 61 a 75, por exemplo:
1
SELECT coluna FROM tabela LIMIT 15 OFFSET 60;
Com este recurso, fica fácil paginar os resultados de uma SQL e mostrar ao usuário apenas a página, ao invés de retornar todos os registros da tabela. Uma tabela com 2000 registros, por exemplo, fica muito melhor mostrar ao usuário de 10 em 10, por exemplo, e diminui a carga no banco de dados, melhorando a sua performance.

quarta-feira, 25 de março de 2015

Alterando Tablespace de Tabelas e Indices no PostgreSQL





ALTERANDO AS TABELAS
– Cria TableSpace
CREATE TABLESPACE “banco_data” OWNER postgres LOCATION ‘/postgres/pg825/dados/pg_tblspc/banco_data';
– verifica se as tablespaces foram criadas
SELECT spcname AS “Tablespace”,
pg_size_pretty(pg_tablespace_size (spcname)) AS “Tamanho”,
spclocation as “Caminho”
FROM pg_tableSpace;
– Gera Script para alterar tabelas
SELECT ‘ALTER TABLE’ ,n.nspname AS schemaname,’.’, c.relname AS tablename, ‘SET TABLESPACE banco_data;’
FROM pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_tablespace t ON t.oid = c.reltablespace
WHERE c.relkind = ‘r'::”char”
AND nspname NOT IN
(‘dbateste’,’information_schema’,’pg_catalog’,’pg_temp_1′,’pg_toast’,’postgres’,’publico’,’public’)
ORDER BY n.nspname
– Confere alteracao das tabelas
SELECT n.nspname AS schemaname, c.relname AS tablename, t.spcname AS “Tablespace”
FROM pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_tablespace t ON t.oid = c.reltablespace
WHERE c.relkind = ‘r'::”char”
AND nspname NOT IN
(‘dbateste’,’information_schema’,’pg_catalog’,’pg_temp_1′,’pg_toast’,’postgres’,’publico’,’public’)
ORDER BY n.nspname, c.relname
– Verifica tabelas sem tablespace
SELECT n.nspname AS schemaname, c.relname AS tablename, t.spcname AS “Tablespace”
FROM pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_tablespace t ON t.oid = c.reltablespace
WHERE c.relkind = ‘r'::”char”
AND nspname NOT IN
(‘dbateste’,’information_schema’,’pg_catalog’,’pg_temp_1′,’pg_toast’,’postgres’,’publico’,’public’)
AND t.spcname IS NULL
ORDER BY t.spcname DESC

– Verifica tamanho da tablespace
SELECT spcname AS “Tablespace”,
pg_size_pretty(pg_tablespace_size (spcname)) AS “Tamanho”,
spclocation as “Caminho”
FROM pg_tableSpace;
ALTERANDO OS INDICES
– Cria TableSpace
CREATE TABLESPACE “banco_idx” OWNER postgres LOCATION ‘/postgres/pg825/dados/pg_tblspc/banco_idx';
– verifica se as tablespaces foram criadas
SELECT spcname AS “Tablespace”,
pg_size_pretty(pg_tablespace_size (spcname)) AS “Tamanho”,
spclocation as “Caminho”
FROM pg_tableSpace;
– Verifica quais sao os indices ( Nao primarios) e o tamanho
SELECT n.nspname AS schemaname,c.relname AS tablename,
c.relpages::numeric * 4.096 / 1024::numeric AS espaco_mb
FROM pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_tablespace t ON t.oid = c.reltablespace
LEFT JOIN pg_index x ON x.indexrelid = c.oid
WHERE c.relkind = ‘i'::”char”
AND x.indisprimary != ‘t’
AND x.indisunique != ‘t’
AND nspname NOT IN
(‘dbateste’,’information_schema’,’pg_catalog’,’pg_temp_1′,’pg_toast’,’postgres’,’publico’,’public’)
ORDER BY n.nspname
– Gera Script para alterar indices
SELECT ‘ALTER INDEX’, n.nspname AS schemaname , ‘.’ ,c.relname AS tablename, ‘SET TABLESPACE banco_idx;’
FROM pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_tablespace t ON t.oid = c.reltablespace
LEFT JOIN pg_index x ON x.indexrelid = c.oid
WHERE c.relkind = ‘i'::”char”
AND x.indisprimary != ‘t’
AND x.indisunique != ‘t’
AND nspname NOT IN
(‘dbateste’,’information_schema’,’pg_catalog’,’pg_temp_1′,’pg_toast’,’postgres’,’publico’,’public’)
ORDER BY n.nspname
– Confere alteracao dos indices
SELECT n.nspname AS schemaname ,c.relname AS tablename,t.spcname AS “Tablespace”
FROM pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_tablespace t ON t.oid = c.reltablespace
LEFT JOIN pg_index x ON x.indexrelid = c.oid
WHERE c.relkind = ‘i'::”char”
AND x.indisprimary != ‘t’
AND x.indisunique != ‘t’
AND nspname NOT IN
(‘dbateste’,’information_schema’,’pg_catalog’,’pg_temp_1′,’pg_toast’,’postgres’,’publico’,’public’)
ORDER BY n.nspname
– Verifica indice sem tablespace
SELECT n.nspname AS schemaname ,c.relname AS tablename,t.spcname AS “Tablespace”
FROM pg_class c
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_tablespace t ON t.oid = c.reltablespace
LEFT JOIN pg_index x ON x.indexrelid = c.oid
WHERE c.relkind = ‘i'::”char”
AND x.indisprimary != ‘t’
AND x.indisunique != ‘t’
AND nspname NOT IN
(‘dbateste’,’information_schema’,’pg_catalog’,’pg_temp_1′,’pg_toast’,’postgres’,’publico’,’public’)
AND t.spcname IS NULL
ORDER BY t.spcname DESC

– Verifica tamanho da tablespace
SELECT spcname AS “Tablespace”,
pg_size_pretty(pg_tablespace_size (spcname)) AS “Tamanho”,
spclocation as “Caminho”
FROM pg_tableSpace;

terça-feira, 10 de fevereiro de 2015

Upgrade de PostgreSQL 9.3 para 9.4 (em CentOS 7)

[root@localhost ~]# su - postgres
Last login: Thu Dec 25 04:31:05 EST 2014 on pts/0
-bash-4.2$ pg_dumpall > backup.sql
-bash-4.2$ exit
logout
[root@localhost ~]# wget http://yum.postgresql.org/9.4/redhat/rhel-7-x86_64/pgdg-centos94-9.4-1.noarch.rpm
--2014-12-25 04:33:01--  http://yum.postgresql.org/9.4/redhat/rhel-7-x86_64/pgdg-centos94-9.4-1.noarch.rpm
Resolving yum.postgresql.org (yum.postgresql.org)... 174.143.35.196, 2001:4800:1501:1::196
Connecting to yum.postgresql.org (yum.postgresql.org)|174.143.35.196|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 5328 (5.2K) [application/x-redhat-package-manager]
Saving to: ‘pgdg-centos94-9.4-1.noarch.rpm’

100%[==============================================>] 5,328       --.-K/s   in 0.002s  

2014-12-25 04:33:08 (2.46 MB/s) - ‘pgdg-centos94-9.4-1.noarch.rpm’ saved [5328/5328]

[root@localhost ~]# rpm -ivh pgdg-centos94-9.4-1.noarch.rpm 
Preparing...                          ################################# [100%]
Updating / installing...
   1:pgdg-centos94-9.4-1              ################################# [100%]
[root@localhost ~]# systemctl stop postgresql-9.3
[root@localhost ~]# yum -y install postgresql94 postgresql94-devel postgresql94-contrib postgresql94-libs postgresql94-test postgresql94-server postgresql94-docs
Loaded plugins: fastestmirror
base                                                                                                                                            | 3.6 kB  00:00:00     
extras                                                                                                                                          | 3.4 kB  00:00:00     
pgdg93                                                                                                                                          | 3.6 kB  00:00:00     
pgdg94                                                                                                                                          | 3.6 kB  00:00:00     
updates                                                                                                                                         | 3.4 kB  00:00:00     
Loading mirror speeds from cached hostfile
 * base: mirror.powerhost.cl
 * extras: centos.ufms.br
 * updates: centos.ufms.br
Resolving Dependencies
--> Running transaction check
---> Package postgresql94.x86_64 0:9.4.0-1PGDG.rhel7 will be installed
---> Package postgresql94-contrib.x86_64 0:9.4.0-1PGDG.rhel7 will be installed
---> Package postgresql94-devel.x86_64 0:9.4.0-1PGDG.rhel7 will be installed
---> Package postgresql94-docs.x86_64 0:9.4.0-1PGDG.rhel7 will be installed
---> Package postgresql94-libs.x86_64 0:9.4.0-1PGDG.rhel7 will be installed
---> Package postgresql94-server.x86_64 0:9.4.0-1PGDG.rhel7 will be installed
---> Package postgresql94-test.x86_64 0:9.4.0-1PGDG.rhel7 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

====================================================================================
 Package                                        Arch                             Version                                        Repository                        Size
====================================================================================
Installing:
 postgresql94                                   x86_64                           9.4.0-1PGDG.rhel7                              pgdg94                           1.0 M
 postgresql94-contrib                           x86_64                           9.4.0-1PGDG.rhel7                              pgdg94                           601 k
 postgresql94-devel                             x86_64                           9.4.0-1PGDG.rhel7                              pgdg94                           1.6 M
 postgresql94-docs                              x86_64                           9.4.0-1PGDG.rhel7                              pgdg94                            13 M
 postgresql94-libs                              x86_64                           9.4.0-1PGDG.rhel7                              pgdg94                           201 k
 postgresql94-server                            x86_64                           9.4.0-1PGDG.rhel7                              pgdg94                           3.8 M
 postgresql94-test                              x86_64                           9.4.0-1PGDG.rhel7                              pgdg94                           1.3 M

Transaction Summary
==========================================================================================
Install  7 Packages

Total download size: 22 M
Installed size: 72 M
Downloading packages:
(1/7): postgresql94-contrib-9.4.0-1PGDG.rhel7.x86_64.rpm                                                                                        | 601 kB  00:00:02     
(2/7): postgresql94-devel-9.4.0-1PGDG.rhel7.x86_64.rpm                                                                                          | 1.6 MB  00:00:01     
(3/7): postgresql94-9.4.0-1PGDG.rhel7.x86_64.rpm                                                                                                | 1.0 MB  00:00:17     
(4/7): postgresql94-docs-9.4.0-1PGDG.rhel7.x86_64.rpm                                                                                           |  13 MB  00:00:13     
(5/7): postgresql94-libs-9.4.0-1PGDG.rhel7.x86_64.rpm                                                                                           | 201 kB  00:00:00     
(6/7): postgresql94-server-9.4.0-1PGDG.rhel7.x86_64.rpm                                                                                         | 3.8 MB  00:00:04     
(7/7): postgresql94-test-9.4.0-1PGDG.rhel7.x86_64.rpm                                                                                           | 1.3 MB  00:00:05     
---------------------------------------------------------------------------------------
Total                                                                                                                                  933 kB/s |  22 MB  00:00:23     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : postgresql94-libs-9.4.0-1PGDG.rhel7.x86_64                                                                                                          1/7 
  Installing : postgresql94-9.4.0-1PGDG.rhel7.x86_64                                                                                                               2/7 
  Installing : postgresql94-devel-9.4.0-1PGDG.rhel7.x86_64                                                                                                         3/7 
  Installing : postgresql94-server-9.4.0-1PGDG.rhel7.x86_64                                                                                                        4/7 
  Installing : postgresql94-test-9.4.0-1PGDG.rhel7.x86_64                                                                                                          5/7 
  Installing : postgresql94-contrib-9.4.0-1PGDG.rhel7.x86_64                                                                                                       6/7 
  Installing : postgresql94-docs-9.4.0-1PGDG.rhel7.x86_64                                                                                                          7/7 
  Verifying  : postgresql94-contrib-9.4.0-1PGDG.rhel7.x86_64                                                                                                       1/7 
  Verifying  : postgresql94-test-9.4.0-1PGDG.rhel7.x86_64                                                                                                          2/7 
  Verifying  : postgresql94-9.4.0-1PGDG.rhel7.x86_64                                                                                                               3/7 
  Verifying  : postgresql94-devel-9.4.0-1PGDG.rhel7.x86_64                                                                                                         4/7 
  Verifying  : postgresql94-docs-9.4.0-1PGDG.rhel7.x86_64                                                                                                          5/7 
  Verifying  : postgresql94-server-9.4.0-1PGDG.rhel7.x86_64                                                                                                        6/7 
  Verifying  : postgresql94-libs-9.4.0-1PGDG.rhel7.x86_64                                                                                                          7/7 

Installed:
  postgresql94.x86_64 0:9.4.0-1PGDG.rhel7              postgresql94-contrib.x86_64 0:9.4.0-1PGDG.rhel7         postgresql94-devel.x86_64 0:9.4.0-1PGDG.rhel7         
  postgresql94-docs.x86_64 0:9.4.0-1PGDG.rhel7         postgresql94-libs.x86_64 0:9.4.0-1PGDG.rhel7            postgresql94-server.x86_64 0:9.4.0-1PGDG.rhel7        
  postgresql94-test.x86_64 0:9.4.0-1PGDG.rhel7        

Complete!
[root@localhost ~]# /usr/pgsql-9.4/bin/postgresql94-setup initdb
Initializing database ... OK

[root@localhost ~]# systemctl enable postgresql-9.4
ln -s '/usr/lib/systemd/system/postgresql-9.4.service' '/etc/systemd/system/multi-user.target.wants/postgresql-9.4.service'
[root@localhost ~]# systemctl disable postgresql-9.3
rm '/etc/systemd/system/multi-user.target.wants/postgresql-9.3.service'
[root@localhost ~]# systemctl start postgresql-9.4
[root@localhost ~]# su - postgres
Last login: Thu Dec 25 04:31:31 EST 2014 on pts/0
-bash-4.2$ psql
psql (9.4.0)
Type "help" for help.

postgres=# \q
-bash-4.2$ psql < backup.sql 
SET
SET
SET
ERROR:  role "postgres" already exists
ALTER ROLE
REVOKE
REVOKE
GRANT
GRANT
You are now connected to database "postgres" as user "postgres".
SET
SET
SET
SET
SET
SET
SET
COMMENT
CREATE EXTENSION
COMMENT
REVOKE
REVOKE
GRANT
GRANT
You are now connected to database "template1" as user "postgres".
SET
SET
SET
SET
SET
SET
SET
COMMENT
CREATE EXTENSION
COMMENT
REVOKE
REVOKE
GRANT
GRANT
-bash-4.2$

Como instalar PostgreSQL 9.4 no CentOS e sistemas derivados

Para instalar o programa no CentOS 6.4, 6.5 e 7, e ainda poder receber automaticamente as futuras atualizações dele, você deve fazer o seguinte:
Passo 1. Abra um terminal;
Passo 2. Confira se o seu sistema é de 32 bits ou 64 bits, para isso, use o seguinte comando no terminal:
uname -m
Passo 3. Se seu sistema é um CentOS 6.x de 32 bits, use o comando abaixo para adicionar o repositório do PostgreSQL 9.4:
rpm -Uvh http://yum.postgresql.org/9.4/redhat/rhel-6-i386/pgdg-centos94-9.4-1.noarch.rpm
Passo 4. Se seu sistema é um CentOS 6.x de 64 bits, use o comando abaixo para adicionar o repositório do PostgreSQL 9.4:
rpm -Uvh http://yum.postgresql.org/9.4/redhat/rhel-6-x86_64/pgdg-centos94-9.4-1.noarch.rpm
Passo 5. Se seu sistema é um CentOS 7 de 64 bits, use o comando abaixo para adicionar o repositório do PostgreSQL 9.4:
rpm -Uvh http://yum.postgresql.org/9.4/redhat/rhel-7-x86_64/pgdg-centos94-9.4-1.noarch.rpm
Passo 6. Atualize o gerenciador de pacotes com o comando:
yum update
Passo 7. Agora use o comando abaixo para instalar o programa;
yum install postgresql94-server postgresql94-contrib
Pronto! Agora, se o banco não for inicializado na instalação, reinicie o sistema e quando quiser, verifique a versão do PostgreSQL usando o seguinte comando em um terminal:
psql --version

CRIANDO USUÁRIOS NO POSTGRESQL


Os usuários de banco de dados são, de forma conceitual, completamente separados de qualquer usuário comum de sistema operacional. 


Na prática isto pode ser conveniente para manter a correspondência, mas não é exigido. Para criar um usuário, utilize o comandocreateuser



Iremos utilizar o shell do Linux para criar usuário, você deve estar como root. 



Parâmetros essenciais para utilizar o createuser:

  • -a = Permite criar novos usuários;
  • -A = Proíbe criar novos usuários;
  • -d = Permite criar novas bases de dados;
  • -D = Proíbe criar novas bases de dados;
  • -E = Encripta Senha do usuário;
  • -P = Solicita senha do novo usuário.



Criando um usuário normal: 



# createuser -A -D -E -P usuário 



Criando usuário admin: 



# createuser -a -d -E -P usuário 



Definindo a senha do usuário: 



# passwd usuário 

FAZENDO BACKUP DE UM SERVIDOR INTEIRO


Imagine que precisemos reinstalar o sistema operacional de nosso servidor de banco de dados, que roda o SGBD PostgreSQL 8.3. Bom, precisamos fazer um backup de nossos dados e saber como restaurar depois, né?! 


Para isso podemos usar ferramentas fornecidas pelo Postgre. Diferente de alguns outros SGBD, o backup no Postgre não é feito via linguagem de consulta (SQL), mas sim via aplicações. O PostgreSQL disponibiliza alguns programas (comandos) para que possam ser efetuados backups. 



Também é possível trabalhar com algum frontend (o pgAdmin por exemplo), mas como geralmente servidores Linux não possuem interface gráfica, é bom sempre ver como fazer tudo sem o mouse e só naquela telinha preta. 



A ferramenta oferecida para fazer um dump de um servidor em um arquivo plain (sql) é o pg_dumpall. Este comando é capaz de fazer o backup de todos os dados de um determinado servidor. Exemplo: 



# pg_dumpall -h localhost -p 5432 -U postgres -v -f "/backup/dbserver.sql" 



Este comando fará o backup do servidor localhost (argumento -h), na porta 5432 (argumento -p), com o usuário postgres (argumento -U), no modo interativo (verbose - argumento -v), e salvará o backup no arquivo /backup/dbserver.sql (argumento -f). 



Após a formatação do nosso servidor e reinstalação do sistema operacional, podemos facilmente restaurar o backup com a ferramenta psql, antes é necessário acessar o terminal com o usuário postgres: 



# su postgres
$ psql -f /backup/dbserver.sql 

FAZENDO BACKUP COM POSTGRESQL

PostgreSQL oferece boas ferramentas para backup. Nesta dica vou explicar o funcionamento do pg_dump, a ferramenta mais usada para fazer backup no PostgreSQL. 

No console do PostgreSQL no Linux, digite o seguinte comando: 

$ pg_dump <nome_da_base_de_dados> > nome_arq_texto_bkp 

Onde:
  • nome_da_base_de_dados: é o nome do banco de dados que você quer fazer o backup.
  • nome_arq_texto_bkp: este vai ser o arquivo que guardará todas as informações do banco de dados.

OBS: Este comando faz uma exportação de todo o banco de dados, ou seja, dados e tabelas (estrutura). 

Mas se você quiser exportar apenas uma tabela: 

$ pg_dump <nome_da_base_de_dados> -t <nome_da_tabela> > nome_arq_texto_bkp 

Isto faz uma exportação de uma tabela específica dentro do banco. 

Para retornar o backup faça: 

$ psql -e <nome_da_base_de_dados> < nome_arq_texto_bkp 

segunda-feira, 17 de novembro de 2014

PostgreSQL VACUUM: Limpando o Banco de dados

É muito importante, principalmente para um DBA, conhecer e analisar as ferramentas que possam aumentar a performance do banco de dados, isso porque geralmente empresas que possuem DBA trabalham com uma grande quantidade de dados e a velocidade de resposta da aplicação torna-se crítica para seu negócio. Imagine, por exemplo, uma Operadora de Cartão de Crédito, como Visa ou Mastercard: quantos milhões de transações por segundo são realizadas em todo mundo? É fato que um index errado em um banco de dados dessa operadora pode ser fatal para perda de milhões de reais em poucos segundos.
VACUUM
Antes de entender como funciona tal técnica é importante conhecer o funcionamento interno do PostgreSQL para assim ver a real utilidade da mesma.

Você já percebeu que ao deletar registros do seu banco de dados ele não diminui ? Faça o teste: compare o tamanho atual do seu banco de dados com o tamanho após a deleção de muitos registros, você ficará surpreso ao perceber que nada mudou. Então você deve se perguntar: Mas se eu estou deletando, o mais lógico é diminuir o tamanho do banco, certo? Negativo. O PostgreSQL, assim como outros bancos, na verdade não deletam os registros e sim os marca como inúteis, técnica muito comum e utilizada em diversas aplicações, ou seja, se você fizer um “DELETE FROM funcionario WHERE id > 100” e este comando deletar 10 mil linhas, você na verdade estará marcando as 10 mil linhas como inúteis e não deletando fisicamente, o que demandaria muito mais tempo e recurso.

A lógica é a seguinte:é muito melhor ter uma operação rápida do que espaço em disco, sendo assim o banco ficará enorme mais sua performance compensará tal perda de espaço, que hoje em dia acaba não trazendo muito impacto, já que 'armazenamento digital' está barato e acessível.

Todo esse mecanismo é chamado de MVCC (Multiversion Concurrency Control) que garante uma performance melhor ao banco de dados, afinal performance é o ponto chave em aplicações críticas. Quando você realiza um UPDATE, o seu registro é atualizado, correto? Negativo. O que na verdade é feito é uma inserção de outra tupla na sua tabela, com os mesmos dados da tupla original, apenas alterando o que você solicitou no UPDATE, e a tupla anterior (não atualizada) é marcada como inútil, assim como explicamos no DELETE.

Dado todas as explicações acima, chegamos ao ponto chave do artigo: a utilização do VACUUM. Já que temos muitos registros que estão marcados como inúteis, precisamos em algum momento limpar estes, para garantir ainda mais performance em nosso banco e retirar toda sujeira de dados.

No momento em que o comando VACUUM é executado, é feita uma varredura em todo o banco a procura de registros inúteis, onde estes são fisicamente removidos, agora sim diminuindo o tamanho físico do banco. Mas além de apenas remover os registros, o comando VACUUM encarrega-se de organizar os registros que não foram deletados, garantindo que não fiquem espaços/lacunas em branco após a remoção dos registros inúteis.
Figura 1. Executando Vacuum
Na Figura 1 você pode notar um exemplo simples e prático de como funciona o Vacuum:
  1. Temos na Listagem 1 a lista de todos os registros, incluindo os úteis e inúteis (marcados em vermelho).
  2. O vacuum deleta todos os registros inúteis (em vermelho), mas após essas deleções serem realizadas, você pode perceber que ficam espaços em branco, exatamente o espaço onde estavam os registros inúteis.
  3. Por fim, o vacuum encarrega-se de remover esses espaços, garantindo que os mesmos fiquem organizados e em uma disposição correta.
Há ainda um quarto e último passo realizado pelo vacuum, que não está descrito na figura acima. Ocorre que o vacuum também atualiza as estatísticas que são utilizadas pelo otimizador do PostgreSQL para determinar qual a melhor forma de realizar uma busca no banco de dados, porém, a atualização dessas estatísticas vai depender da forma em que o vacuum for executado, o que explicaremos mais a frente do porque.

Listagem 1. Sintaxe do Vacuum
  VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ tabela ]
  VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] 
  ANALYZE [ tabela [ (coluna  [, ...] ) ]]  
Acima você pode ver toda a parametrização do comando vacuum, com suas possíveis opções, então vamos explicar cada uma delas e sua utilidade:
  • # FULL : Quando o vacuum é utilizado em conjunto com este parâmetro, então é feita uma limpeza completa de todo o banco, em todas as tabelas e colunas. Este processo geralmente é demorado e evita que qualquer outra operação no banco seja realizada, ou seja, ao realizar um VACUUM FULL você terá que esperar todo processo terminar até realizar um comando DLL ou DML.
  • # VERBOSE: Ao ativar esse parâmetro você terá um relatório detalhado de tudo que está sendo feito no comando VACUUM.
  • # ANALYSE: Você lembra que citamos anteriormente que o VACUUM em um último passo pode ou não atualizar as estatística que são utilizadas pelo otimizador do PostgreSQL para determinar o melhor método de consulta? Este parâmetro é responsável por habilitar ou desabilitar este tipo de atualização, em outras palavras, ao usar o ANALYSE junto ao seu comando VACUUM ele irá atualizar as estatística do banco de dados a fim de melhorar a performance das pesquisas.
  • # tabela: Caso você queira realizar o VACUUM apenas em uma tabela, então você deve especificar explicitamente qual tabela será, caso contrário, apenas deixe este parâmetro em branco e todas as tabelas serão consideradas.
  • # coluna: Seguindo o mesmo raciocínio da tabela, caso você deseje realizar o VACUUM em apenas algumas colunas, basta especificar quais são, caso contrário, deixe este parâmetro em branco e todas as colunas serão consideradas.
Algo que você pode ser perguntar é qual a diferença entre o VACUUM sem parâmetros (simples) e o VACUUM FULL (que exige o bloqueio exclusivo das tabelas, ou seja, nenhuma operação pode ser realizada enquanto este comando estiver em processamento). O VACUUM simples apenas remove as tuplas marcadas como inúteis/removidas em processos de UPDATE ou DELETE. Sendo assim, não há necessidade de bloquear as operações no banco. Por outro lado, o VACUUM FULL além de remover essas tuplas inúteis, ainda reorganiza as tabelas, retirando os espaços em branco que ficaram após a remoção dessas colunas, e para tal processo é necessário que o banco não esteja realizando nenhuma operação, por isso o bloqueio do mesmo é necessário.

Caso você utilize o pgAdmin como uma ferramenta para realizar o gerenciamento do seu PostgreSQL, então nele mesmo (sem linha de comando) você poderá realizar o VACUUM, assim como outros processos otimizadores de performance.

O processo é simples: basta você clicar com o botão direito em cima da sua base de dados e depois escolher a opção “Maintenance...”, então você verá uma janela como mostrada na Figura 2.


Figura 2. Vacuum no pgAdmin III

O Vacuum diminui consideravelmente o tamanho físico do banco, mas não só isso, ele também aumenta a performance do otimizador do banco de dados. Além dele, ainda existem outras ferramentas, como falamos em seções anteriores. No gráfico da Figura 3 você pode visualizar de forma mais abrangente a diferença física de espaço em seu banco após realizar processos de otimização do banco, tais como: vacuum, reindex e outros.

Figura 3. Gráfico PostgreSQL após otimização

O próprio PostgreSQL já possui um processo chamado autovacuum onde você pode deixar que o próprio banco realize o Vacuum Simples (sem o FULL) com frequência, o que é muito bom para base de dados, pois as deleções e atualizações de registros são constantes e você mantêm sua base sempre rápida e sem dados sujos. Por outro lado, a própria documentação original do PostgreSQL aconselha que o VACUUM FULL seja usado como muito cuidado e em casos raros, isso porque o processo demanda muito tempo e pode até causar baixa de performance no banco, em vez de melhor a mesma, isso porque o processo faz algo muito crítico, que é a reorganização de todas as tuplas, retirando os 'gaps' que ficaram após a remoção dos registros inúteis.

Com isso, este artigo teve como principal objetivo demonstrar técnicas mais avançadas do PostgreSQL para análise de performance e otimização do banco, assunto este essencial e obrigatório para DBA's. Vale ressaltar que todas as técnicas descritas neste artigo devem ser usadas com cautela e sempre mediante a uma análise prévia do problema, em outras palavras, não saia executando VACUUM em todas as suas tabelas e bancos antes de analisar a real necessidade de aplicar este procedimento. Como citamos anteriormente, a própria documentação do PostgreSQL aconselha o não uso do VACUUM FULL, que pode ser prejudicial ao banco de dados, se aplicado de forma errônea, obviamente.

segunda-feira, 10 de novembro de 2014

PostgreSQL Prático/Metadados

Metadados são dados sobre dados.
Uma consulta normal retorna informações existentes em tabelas, já uma consulta sobre os metadados retorna informações sobre os bancos, os objetos dos bancos, os campos de tabelas, seus tipos de dados, seus atributos, suas constraints, etc.
Retornar Todas as Tabelas do banco e esquema atual
SELECT schemaname AS esquema, tablename AS tabela, tableowner AS dono
 FROM pg_catalog.pg_tables
 WHERE schemaname NOT IN ('pg_catalog', 'information_schema', 'pg_toast')
 ORDER BY schemaname, tablename
Informações de Todos os Tablespaces
SELECT spcname, pg_catalog.pg_get_userbyid(spcowner) AS spcowner, spclocation
 FROM pg_catalog.pg_tablespace
Retornar banco, dono, codificação, comentários e tablespace
SELECT pdb.datname AS banco, 
 pu.usename AS dono, 
 pg_encoding_to_char(encoding) AS codificacao,
 (SELECT description FROM pg_description pd WHERE pdb.oid=pd.objoid) AS comentario,
 (SELECT spcname FROM pg_catalog.pg_tablespace pt WHERE pt.oid=pdb.dattablespace) AS tablespace
 FROM pg_database pdb, pg_user pu WHERE pdb.datdba = pu.usesysid ORDER BY pdb.datname
Tabelas, donos, comentários, registros e tablespaces de um schema
SELECT c.relname as tabela, 
 pg_catalog.pg_get_userbyid(c.relowner) AS dono, 
 pg_catalog.obj_description(c.oid, 'pg_class') AS comentario, reltuples::integer as registros,
 (SELECT spcname FROM pg_catalog.pg_tablespace pt WHERE pt.oid=c.reltablespace) AS tablespace
 FROM pg_catalog.pg_class c
 LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
 WHERE c.relkind = 'r' AND nspname='public'
 ORDER BY c.relname
Mostrar Sequences de um Esquema
SELECT c.relname AS seqname, u.usename AS seqowner, pg_catalog.obj_description(c.oid, 'pg_class') AS seqcomment,
    (SELECT spcname FROM pg_catalog.pg_tablespace pt WHERE pt.oid=c.reltablespace) AS tablespace
     FROM pg_catalog.pg_class c, pg_catalog.pg_user u, pg_catalog.pg_namespace n
     WHERE c.relowner=u.usesysid AND c.relnamespace=n.oid
     AND c.relkind = 'S' AND n.nspname='public' ORDER BY seqname
Mostrar Sequences de um Esquema
SELECT c.relname AS seqname, u.usename AS seqowner, pg_catalog.obj_description(c.oid, 'pg_class') AS seqcomment,
    (SELECT spcname FROM pg_catalog.pg_tablespace pt WHERE pt.oid=c.reltablespace) AS tablespace
     FROM pg_catalog.pg_class c, pg_catalog.pg_user u, pg_catalog.pg_namespace n
     WHERE c.relowner=u.usesysid AND c.relnamespace=n.oid
     AND c.relkind = 'S' AND n.nspname='public' ORDER BY seqname
Mostrar Esquemas e respectivas tabelas do Banco atual:
SELECT n.nspname as esquema, c.relname as tabela  FROM pg_namespace n, pg_class c
 WHERE n.oid = c.relnamespace
   and c.relkind = 'r'     -- no indices
   and n.nspname not like 'pg\\_%' -- no catalogs
   and n.nspname != 'information_schema' -- no information_schema
 ORDER BY nspname, relname
Dado o banco de dados, qual o seu diretório:
select datname, oid from pg_database;
Dado a tabela, qual o seu arquivo:
select relname, relfilenode from pg_class;
Tamanho em bytes de um banco:
select pg_database_size('banco');
Tamanho em bytes de uma tabela:
pg_total_relation_size('tabela')
Tamanho em bytes de tabela ou índice:
pg_relation_size('tabelaouindice')

Lista donos e bancos:
SELECT rolname as dono, datname as banco
FROM pg_roles, pg_database
WHERE pg_roles.oid = datdba
ORDER BY rolname, datname;
Nomes de bancos:
select datname from pg_database where datname not in ('template0','template1') order by 1