Boas praticas em um Projeto de Banco de Dados

41
Juliano Atanazio Boas Práticas em um Projeto de Banco de Dados

Transcript of Boas praticas em um Projeto de Banco de Dados

Page 1: Boas praticas em um Projeto de Banco de Dados

Juliano Atanazio

Boas Práticas em um Projeto de Banco de Dados

Page 2: Boas praticas em um Projeto de Banco de Dados

2/41

Antes de Tudo...

Conheça bem:

● seu hardware;

● seu sistema operacional;

● as entidades tratadas na base de dados.

Page 3: Boas praticas em um Projeto de Banco de Dados

3/41

Servidores

● Mantenha em servidores separados a aplicação que acessa o banco e o servidor de banco de dados;

● É mais seguro e evita competição de recursos entre os serviços;

● No servidor de banco de dados ter no mínimo discos separados para sistema operacional, dados e logs de transação;

● Configure apropriadamente logs do servidor de aplicação e do servidor de banco de dados;

● Não deixe o servidor de banco de dados exposto na Internet;

● Ter estratégias de backup e alta disponibilidade.

Page 4: Boas praticas em um Projeto de Banco de Dados

4/41

O Projeto de Banco de Dados

● Investir não é gastar...;

● Invista seu tempo para uma modelagem e projeto de banco de dados bem feita;

● Pense como uma construção de um prédio, pois o projeto de banco de dados é um dos alicerces para seu sistema;

● É melhor prevenir do que remediar, pois o tempo investido para uma modelagem bem consolidada será recompensado em não ter que fazer manutenções (desnecessárias, a priori) e ter que projetar novamente mais tarde, pois aí seria gasto muito mais tempo do que o investido no início;

● Para o projeto da base de dados deve-se trabalhar em conjunto DBAs, desenvolvedores e gestores de projetos.

Page 5: Boas praticas em um Projeto de Banco de Dados

5/41

Nomenclaturas de Objetos

● Seja qual for o padrão adotado, siga-o até o fim!;

● Prefixos / sufixos: utilizar ou não? Bases de Dados, tabelas, views, triggers, etc... adote iniciais, tais como db_, tb_, vw_, tg_... Considere os prós e contras, mas não misture!;

● Utilizar nomes amigáveis para os objetos conforme a entidade tratada;

● Nomes de tabelas no singular;

● Jamais utilizar acentuação ou qualquer caractere especial;

Page 6: Boas praticas em um Projeto de Banco de Dados

6/41

Nomenclaturas de Objetos

● Não utilizar nomes com espaços e / ou letras maiúsculas;

● Para nomes de campos, se possível utilizar o mesmo nome para a chave primária em todas as tabelas, como “id” ou “cod”, por exemplo;

● Campos que têm o mesmo propósito em tabelas diferentes, preferencialmente ter o mesmo nome;

● Nomes de campos também devem ser padronizados;

● Evite coisas como na tabela “A” há um campo “data_inicio” e na tabela “B” o campo se chama “data_ini”...

Page 7: Boas praticas em um Projeto de Banco de Dados

7/41

Usuários / Grupos / Papéis

● Dê o mínimo de privilégios necessários para cada usuário conforme o objeto que acessa ou usa;

● Utilize grupos de usuários para facilitar sua gestão, agrupando-os por algum setor e / ou características em comum;

● Alguns parâmetros de configuração (os de sessão) podem servir de configuração para um papel (role) específico e dependendo do caso, conforme a necessidade é bom fazê-lo. Por exemplo, um usuário que precisa ser sempre auditado:

ALTER ROLE foo SET log_statement = 'all';

Page 8: Boas praticas em um Projeto de Banco de Dados

8/41

Views

● Views podem ser grandes aliadas;

● Podem ser utilizadas para isolar alterações da base de dados da aplicação, reduzindo a necessidade de manutenção se houver alteração na base dados;

● Podem também ser utilizadas para prover acesso granular a usuários.

Page 9: Boas praticas em um Projeto de Banco de Dados

9/41

ORMs

● Não confie cegamente neles.

● Utilize-os com moderação, de forma que se tenha o total controle e total conhecimento sobre sua base.

● Evite transações implícitas, ORMs têm o costume deixar cada comando (statement) ser tratado como uma transação resultando em perda de performance. Desabilite transações explícitas e quando precisar de uma transação faça-a explicitamente.

Page 10: Boas praticas em um Projeto de Banco de Dados

10/41

Documentação

● Documente o esquema da base em esquemas de Entidade-Relacionamento;

● Escreva comentários em seus scripts declarando cada ação de cada comando;

● Utilize comentários de objetos (descrição de objetos).

Page 11: Boas praticas em um Projeto de Banco de Dados

11/41

Tablespaces

● Tabelas e índices cuja utilização e / ou tamanho sejam muito maiores do que os outros é melhor deixar em disco(s) separado(s);

● A partição de tablespace deve ser formatada com um sistema de arquivos primeiramente seguro contra falhas (crashes) e com boa performance de escrita e leitura.

Page 12: Boas praticas em um Projeto de Banco de Dados

12/41

Índices

● Crie índices para campos que são utilizados em condições de consultas, ou pelo menos as consultas mais frequentes;

● Crie índices para campos de chaves estrangeiras e em campos envolvidos como critérios de junção (JOIN);

● Se houver uma consulta frequente utilize índices parciais com sua condição conforme a consulta;

● Para consultas que buscam faixas de valores é bom ter um índice clusterizado para isso;

Page 13: Boas praticas em um Projeto de Banco de Dados

13/41

Índices

● Fillfactor (fator de preenchimento) para um índice é a porcentagem que determina como o método de indexação encherá as páginas de índices. O quão cheias essas páginas ficarão em porcentagem;

● Para tabelas estáticas pode-se deixar em 100 (representando 100%);

● Para tabelas que sofrem muitas alterações um valor de 80 ou menos pode ser mais adequado, mas quanto menor for o fator de preenchimento, mais espaço em disco ocupará.

Page 14: Boas praticas em um Projeto de Banco de Dados

14/41

Evite BLOBs

● Utilize campos bytea, pois BLOBs são armazenados em um catálogo do sistema (pg_largeobject).

● Com campos bytea têm-se a flexibilidade de determinar em qual tabela de sua base de dados o objeto será armazenado.

● Não criar campos bytea em tabelas muito utilizadas, crie uma tabela exclusiva para grandes objetos para ser referenciada.

Page 15: Boas praticas em um Projeto de Banco de Dados

15/41

Integridade de Dados

● Utilize constraints (foreign key, check, not null), não deixe o controle total para a aplicação.

● Evite dados inconsistentes em seu banco de dados, como um preço negativo de um produto, por exemplo.

Page 16: Boas praticas em um Projeto de Banco de Dados

16/41

Consultas

● Evite o famoso SELECT *...

● Para um melhor desempenho declare cada campo que precisar para buscar os dados;

● Evite caracteres curinga com a cláusula LIKE. Isso faz com que o motor do banco de dados não use indexação para uma busca, o que leva a uma performance degradada;

● Pagine sua busca, faça uso de LIMIT e OFFSET, pois não faz sentido uma busca retornar um número exorbitante de linhas. Consome muitos recursos e degrada a performance. Um número razoável é de até 100 (cem) linhas retornadas por vez.

Page 17: Boas praticas em um Projeto de Banco de Dados

17/41

Chaves Primárias

● Sempre tenha uma chave primária na tabela;

● Quando possível fazer uso de chaves naturais;

● Prefira tipos numéricos a tipos de texto, pois consomem menos recursos e são mais rápidos para busca.

Page 18: Boas praticas em um Projeto de Banco de Dados

18/41

Esquemas

● Para a mesma aplicação, que trata das mesmas coisas evite criar mais de uma base de dados;

● Faça uso de schemas para organizar seus objetos.

Page 19: Boas praticas em um Projeto de Banco de Dados

19/41

Tipos de Dados

Não dê tiros em formiga!

● Escolha o tipo certopara sua coluna;

● Consulte a documentação doPostgreSQL [1] verificando seo tipo de dados escolhidoé realmente o mais adequado para nãoderperdiçar recursos.

[1] http://www.postgresql.org/docs/current/static/datatype.html

Page 20: Boas praticas em um Projeto de Banco de Dados

20/41

Tipos de Dados: pg_type_of e pg_column_size

A função pg_typeof pode te ajudar a descobrir um tipo de um dado:

> SELECT pg_typeof(5874.31);

pg_typeof ----------- numeric

A função pg_column_size exibe em bytes o tamanho de um dado

Quantos bytes em numeric?:

> SELECT pg_column_size(5874.31::numeric);

pg_column_size ---------------- 10

Page 21: Boas praticas em um Projeto de Banco de Dados

21/41

Tipos de Dados: pg_type_of e pg_column_size

Quantos bytes em money?:

> SELECT pg_column_size(5874.31::money);

pg_column_size ---------------- 8

Page 22: Boas praticas em um Projeto de Banco de Dados

22/41

Tipos de Dados: Endereço IP

Como text:

> SELECT pg_column_size('192.168.7.1'::text);

pg_column_size ---------------- 15

Como inet:

> SELECT pg_column_size('192.168.7.1'::inet);

pg_column_size ---------------- 10

Page 23: Boas praticas em um Projeto de Banco de Dados

23/41

Tipos de Dados: Endereço de Rede com Máscara

Como text:

> SELECT pg_column_size('192.168.7.0/24'::text);

pg_column_size ---------------- 18

Como cidr:

> SELECT pg_column_size('192.168.7.0/24'::cidr);

pg_column_size ---------------- 10

Page 24: Boas praticas em um Projeto de Banco de Dados

24/41

Tipos de Dados: MAC Address

Como text:

> SELECT pg_column_size('00:00:00:00:00:00'::text);

pg_column_size ---------------- 21

Como macaddr:

> SELECT pg_column_size('00:00:00:00:00:00'::macaddr);

pg_column_size ---------------- 6

Page 25: Boas praticas em um Projeto de Banco de Dados

25/41

Tipos de Dados: Inteiros (int2, int4 e int8)

Criação de tabela com três campos inteiros (smallint, integer e bigint):

SELECT generate_series(1, 10000)::int2 campo_int2,generate_series(1, 10000)::int4 campo_int4,generate_series(1, 10000)::int8 campo_int8INTO tb_inteiros;

Page 26: Boas praticas em um Projeto de Banco de Dados

26/41

Tipos de Dados: Inteiros (int2, int4 e int8)

Quanto cada coluna ocupa em disco:

SELECT pg_size_pretty(sum(pg_column_size(campo_int2))) "smallint",pg_size_pretty(sum(pg_column_size(campo_int4))) "integer",pg_size_pretty(sum(pg_column_size(campo_int8))) "bigint"FROM tb_inteiros;

smallint | integer | bigint ----------+---------+-------- 20 kB | 39 kB | 78 kB

Page 27: Boas praticas em um Projeto de Banco de Dados

27/41

Tipos de Dados:Inteiros vs Texto

Criação de um banco de dados de teste:

> CREATE DATABASE db_teste;

Conexão ao banco:

> \c db_teste

Page 28: Boas praticas em um Projeto de Banco de Dados

28/41

Tipos de Dados:Inteiros vs Texto

Criação de uma tabela de teste:

> CREATE TABLE tb_teste_tipos_de_dados(campo_int2 smallint,campo_int4 int,campo_int8 bigint,campo_text text,campo_varchar_10 varchar(10),campo_char_10 char(10)

);

Page 29: Boas praticas em um Projeto de Banco de Dados

29/41

Tipos de Dados:Inteiros vs Texto

Criação de índices:

> CREATE INDEX idx_campo_int2 ON tb_teste_tipos_de_dados (campo_int2);

> CREATE INDEX idx_campo_int4 ON tb_teste_tipos_de_dados (campo_int4);

> CREATE INDEX idx_campo_int8ON tb_teste_tipos_de_dados (campo_int8);

> CREATE INDEX idx_campo_textON tb_teste_tipos_de_dados (campo_text);

> CREATE INDEX idx_campo_varchar_10ON tb_teste_tipos_de_dados (campo_varchar_10);

> CREATE INDEX idx_campo_char_10ON tb_teste_tipos_de_dados (campo_char_10);

Page 30: Boas praticas em um Projeto de Banco de Dados

30/41

Tipos de Dados:Inteiros vs Texto

Para os testes vamos criar um script em Python (pg_populator.py) com o seguinte conteúdo:

#!/usr/bin/env python#_*_ coding: utf8 _*_

import randomimport sysimport csv

# Quantidade de linhasn_lines = int(sys.argv[1])

try: # Nome do arquivo de saída out_file = sys.argv[2]

except IndexError: # Se nenhum arquivo for informado, enviar # para a saída padrão out_file = '/dev/stdout'

Page 31: Boas praticas em um Projeto de Banco de Dados

31/41

Tipos de Dados:Inteiros vs Texto

for i in xrange(n_lines): # Variáveis com conteúdo aleatório conforme os # campos da tabela int2 = random.randint(-32768, 32767) int4 = random.randint(-2147483648, 2147483647) int8 = random.randint(-9223372036854775808, 9223372036854775807) text = str(int8)[0: 9].zfill(10) varchar_10 = text char_10 = text

line = (int2, int4, int8, text, varchar_10, char_10)

with open(out_file, 'ab') as csvfile: spamwriter = csv.writer(csvfile, delimiter = ';') spamwriter.writerow(line)

Page 32: Boas praticas em um Projeto de Banco de Dados

32/41

Tipos de Dados:Inteiros vs Texto

Damos permissão de execução para ele no shell do Linux:

$ chmod +x pg_populator.py

Gerando um arquivo CSV com dez milhẽs de registros:

$ ./pg_populator.py 10000000 /tmp/arquivo.csv

Importar para o banco:

$ psql -c \"COPY tb_teste_tipos_de_dados FROM '/tmp/arquivo.csv' \DELIMITER ';';" db_teste

Page 33: Boas praticas em um Projeto de Banco de Dados

33/41

Tipos de Dados:Inteiros vs Texto

Verificando o tamanho da tabela:

> SELECT pg_size_pretty(pg_relation_size('tb_teste_tipos_de_dados'))AS "Tamanho da tabela";

Tamanho da tabela ------------------- 766 MB

Qual é o tamanho do índice do campo smallint?:

> SELECTpg_size_pretty(pg_relation_size('idx_campo_int2'))AS "Tamanho do índice do campo smallint";

Tamanho do índice do campo smallint ------------------------------------- 223 MB

Page 34: Boas praticas em um Projeto de Banco de Dados

34/41

Tipos de Dados:Inteiros vs Texto

Qual é o tamanho do índice do campo integer?:

> SELECT pg_size_pretty(pg_relation_size('idx_campo_int4'))AS "Tamanho do índice do campo integer";

Tamanho do índice do campo integer ------------------------------------ 224 MB

Qual é o tamanho do índice do campo bigint?:

> SELECT pg_size_pretty(pg_relation_size('idx_campo_int8'))AS "Tamanho do índice do campo bigint";

Tamanho do índice do campo bigint ----------------------------------- 279 MB

Page 35: Boas praticas em um Projeto de Banco de Dados

35/41

Tipos de Dados:Inteiros vs Texto

Qual é o tamanho do índice do campo text?:

> SELECT pg_size_pretty(pg_relation_size('idx_campo_text'))AS "Tamanho do índice do campo text";

Tamanho do índice do campo text --------------------------------- 333 MB

Qual é o tamanho do índice do campo varchar(10)?:

> SELECT pg_size_pretty(pg_relation_size('idx_campo_varchar_10'))AS "Tamanho do índice do campo varchar(10)";

Tamanho do índice do campo varchar(10) ---------------------------------------- 333 MB

Page 36: Boas praticas em um Projeto de Banco de Dados

36/41

Tipos de Dados:Inteiros vs Texto

Qual é o tamanho do índice do campo char(10)?:

> SELECT pg_size_pretty(pg_relation_size('idx_campo_char_10'))AS "Tamanho do índice do campo char(10)";

Tamanho do índice do campo char(10) ------------------------------------- 333 MB

Page 37: Boas praticas em um Projeto de Banco de Dados

37/41

Tipos de Dados:Inteiros vs Texto

Tamanho de cada coluna:

SELECT pg_size_pretty(sum(pg_column_size(campo_int2))) "smallint",pg_size_pretty(sum(pg_column_size(campo_int4))) "integer",pg_size_pretty(sum(pg_column_size(campo_int8))) "bigint",pg_size_pretty(sum(pg_column_size(campo_text))) "text",pg_size_pretty(sum(pg_column_size(campo_varchar_10))) "varchar(10)",pg_size_pretty(sum(pg_column_size(campo_char_10))) "char(10)"FROM tb_teste_tipos_de_dados;

smallint | integer | bigint | text | varchar(10) | char(10) ----------+---------+--------+--------+-------------+---------- 19 MB | 38 MB | 76 MB | 105 MB | 105 MB | 105 MB

Page 38: Boas praticas em um Projeto de Banco de Dados

38/41

Tipos de Dados:Inteiros vs Texto

ResumoTamanho dos Índices (MB)

Tamanho de cada coluna (MB)

smallint223 19

integer224 38

bigint279 76

text

333 105varchar(10)

char(10

Page 39: Boas praticas em um Projeto de Banco de Dados

39/41

Doe!

O Elefante precisa de você!

Contribua! :)

http://www.postgresql.org/about/donate/

Page 40: Boas praticas em um Projeto de Banco de Dados

40/41

Save our planet!

Page 41: Boas praticas em um Projeto de Banco de Dados

41/41

Até a próxima!!! :)

Juliano Atanazio

[email protected]

https://juliano777.wordpress.com

http://www.slideshare.net/spjuliano

https://speakerdeck.com/julianometalsp

https://br.linkedin.com/pub/juliano-atanazio/2b/951/ab9