Você está na página 1de 111

PROF.

EROS ESTEVÃO DE MOURA

LICENCIATURA EM INFORMÁTICA
Laboratório de Banco de Dados

CACHOEIRO DE ITAPEMIRIM
IFES
2012
Governo Federal
Ministro de Educação
Fernando Haddad
Instituto Federal do Espírito Santo (Ifes)
Reitor
Denio Rebello Arantes
Pró-Reitora de Ensino
Cristiane Tenan Schlittler dos Santos
Diretor-geral do Campus Cachoeiro de Itapemirim
Jorge Mário de Moura Zuany
Diretora do CEAD – Centro de Educação a Distância
Yvina Pavan Baldo
Coordenadores da UAB – Universidade Aberta do Brasil
Marize Lyra Silva Passos
José Mario Costa Junior

Curso de Licenciatura em Informática


Coordenação de Curso
Alexandre Fraga de Araujo
Designer Instrucional
Edmundo Rodrigues Junior
Marcelo Albuquerque Schuster
Professor Formador/Autor
Eros Estevão de Moura

M929L Moura, Eros Estevão de


Laboratório de banco de dados / Eros Estevão de
Moura. Cachoeiro de Itapemirim: Ifes, 2011.
112 p. : il.
ISBN: 978-85-62934-57-5
1. Banco de dados. 2. SQL (Linguagem de
programação de computador). 3. Cliente/servidor
(computadores) I. Instituto Federal de Educação,
Ciência e Tecnologia do Espírito Santo. II. Título.
CDD: 005.74

DIREITOS RESERVADOS
Instituto Federal do Espírito Santo – Ifes
Av. Rio Branco, 50 – Santa Lúcia – Vitória – ES – CEP 29.056-255 – Telefone: (27) 3227-5564

Créditos de autoria da editoração


Capa: Juliana Cristina da Silva
Projeto gráfico: Juliana Cristina da Silva e Nelson Torres
Iconografia: Nelson Torres
Editoração eletrônica: Gráfica Editora Fátima

Revisão de texto:
Esther Ortlieb Faria de Almeida

COPYRIGHT – É proibida a reprodução, mesmo que parcial, por qualquer meio, sem autorização escrita dos
autores e do detentor dos direitos autorais.
Olá, Aluno(a)!

É um prazer tê-lo(a) conosco.

O Ifes – Instituto Federal do Espírito Santo – oferece a você, em parceria


com as Prefeituras e com o Governo Federal, o Curso de Graduação em
Licenciatura em Informática, na modalidade a distância. Apesar de este
curso ser ofertado a distância, esperamos que haja proximidade entre nós,
pois, hoje, graças aos recursos da tecnologia da informação (e-mails, chat,
videoconferência, etc.) podemos manter uma comunicação efetiva.

É importante que você conheça toda a equipe envolvida neste curso: co-
ordenadores, professores especialistas, tutores a distância e tutores presen-
ciais, porque, quando precisar de algum tipo de ajuda, saberá a quem
recorrer.

Na EaD – Educação a Distância, você é o grande responsável pelo sucesso


da aprendizagem. Por isso, é necessário que se organize para os estudos e
para a realização de todas as atividades, nos prazos estabelecidos, confor-
me orientação dos Professores Formadores e Tutores.

Fique atento às orientações de estudo que se encontram no Manual do


Aluno!

A EaD, pela sua característica de amplitude e pelo uso de tecnologias mo-


dernas, representa uma nova forma de aprender, respeitando, sempre, o
seu tempo.

Desejamos-lhe sucesso e dedicação!

Equipe do Ifes
ICONOGRAFIA

Veja, abaixo, alguns símbolos utilizados neste material para guiá-lo em seus estudos.

Fala do Professor

Conceitos importantes. Fique atento!

Atividades que devem ser elaboradas por você,


após a leitura dos textos.

Indicação de leituras complementares, refe-


rentes ao conteúdo estudado.

Destaque de algo importante, referente ao


conteúdo apresentado. Atenção!

Reflexão/questionamento sobre algo impor-


tante referente ao conteúdo apresentado.

Espaço reservado para as anotações que você


julgar necessárias.
APRESENTAÇÃO

Meu nome é Eros Moura, responsável pela disciplina de Laboratório


de Banco de Dados. Atuo como professor do Ifes há 5 anos e já
lecionei em outras instituições de ensino superior (São Camilo e
Unes, ambas em Cachoeiro de Itapemirim-ES). Sou graduado em
Processamento de Dados (1989) pela, hoje, Univer Cidade-Rio de
Janeiro, com pós-graduação em Segurança em Banco de Dados,
pela Universidade Estácio de Sá (2004), no Rio de Janeiro, e tenho
Mestrado em Informática, pela Universidade Candido Mendes
(2006), Rio de Janeiro. Hoje sou doutorando em Produção Vegetal,
pela Universidade Norte Fluminense (UENF). Tenho uma grande
experiência de mercado de trabalho e tive oportunidade de trabalhar
em grandes empresas, como a Embratel e a IBM. Minhas áreas de
interesse são: Banco de Dados, Data Mining, Text Mininge Sistemas
de Suporte a Decisão. Antes de atuar como professor, trabalhei
durante 12 anos como administrador de Banco de Dados (DBA
database administrator). Sou certificado no SGBD Oracle (OCP),
no qual trabalhei a maior parte do tempo.
A disciplina de Laboratório de Banco de Dados tem como objetivo
continuar o estudo de banco de dados que iniciamos na disciplina
de Banco de Dados. Estaremos conhecendo conceitos importantes
para tirar o melhor proveito dos sistemas gerenciadores de banco
de dados.
Nesta disciplina, será utilizado o SGBDR PostGreSQL em nossos
trabalhos. Este software é gratuito (Open Source license).
A fim de que ele seja aproveitado ao máximo por você, seguem
algumas orientações:
-faça a leitura de forma sequencial, evitando saltar partes. Isso, pois
consideramos que, na escrita de cada tópico, o leitor já domina o
tópico anterior;
-faça as atividades propostas assim que terminar de ler cada tópico
ou capítulo, evitando acumular atividades. Essa atitude simples
pode favorecer muito seu desempenho no processo de aprendizagem;
-seja sistemático no seu estudo, evitando ficar muitos dias sem
consultar este material. É importante que você reserve diariamente
um tempo para estudo e para fazer as atividades propostas;
-procure participar de grupos de estudo, aproximando-se de pessoas
com quem você possa estudar. Lembre-se de que seu acesso à Internet
(seja em casa, no trabalho, na instituição de ensino ou em uma lan
house) dá a essa parceria um alcance muito maior.

Este texto está organizado em seis capítulos: o primeiro está


relacionado à análise e comparação de SGBD; o capítulo seguinte
apresenta mais algumas coisas sobre a linguagem SQL que não vimos
na disciplina de Banco de Dados; no terceiro capítulo estaremos vendo
como trabalhar com a SQL em situações simuladas da realidade;
no quarto capítulo estaremos conhecendo sobre transações e acesso
concorrente. Com o foco na administração, no quinto capítulo
estaremos estudando a parte de backup e recuperação em banco de
dados. No sexto e último capítulo, vamos dar uma olhada em como
melhorar a performance de nosso banco de dados.
Meus votos são de que Deus o abençoe, permitindo que você tenha
um ótimo desempenho acadêmico e que aproveite ao máximo em
sua vida profissional as competências desenvolvidas nesta disciplina.
Assim, desejo-lhe bastante sucesso!!!
Prof. Eros Moura
Bons estudos!
Cap. 1 - ANÁLISE E COMPARAÇÃO DE SGBD  11
1.1 Tamanho da Base de Dados  11
1.2 Quantidade de Usuários Simultâneos  12
1.3 Desempenho  12
1.4 Integração  13
1.5 Recursos  13
1.6 O fornecedor  14
1.7 O custo  14
1.8 Conclusão  14

Cap. 2 - SQL AVANÇADO  17


2.1 Store Procedure ou Procedimento Armazenado  17
2.1.1 A sintaxe da simplificada da store procedure no
PostgreSQL  19
2.1.2 Como utilizar store procedure no PostgreSQL  19
2.1.3 Como apagar uma store procedure no PostgreSQL  20
2.1.4 A linguagem PL/pgSQL   20
2.2 Trigger ou gatilho  21
2.2.1 Antes (BEFORE) ou após (AFTER)  22
2.2.2 Para um registro ou para um comando  23
2.2.3 Sintaxe do trigger no PostgreSQL  23
2.2.4 Um exemplo de gatilho no PostgreSQL  24
2.2.5 Teste do gatilho (trigger)  25
2.3 Apagando um gatilho (trigger)  26
2.3.1 Exemplo para apagar um gatilho (trigger)  26
2.4 Um pouco mais sobre visões (views)  26
2.4.1 Sintaxe para criação de visão em SQL  27
2.4.2 Como utilizar uma visão (view)  27
2.4.3 Uso avançado de visões (views)  28
2.5 Como criar um banco de dados no PostgreSQL  29
2.6 Como apagar um banco de dados no PostgreSQL  30

Cap. 3 - SQL NA PRÁTICA  31


3.1 Estudo de Caso 1  31
3.2 Estudo de Caso 2  34
3.3 Estudo de Caso 3  39
3.4 Estudo de Caso 4  41
3.5 Estudo de Caso 5  45
3.6 Estudo de Caso 6  48

Cap. 4 - TRANSAÇÕES E ACESSO CONCORRENTE  53


4.1 A Transação  53
4.1.1 Exemplo do uso da transação  54
4.1.2 Propriedades das Transações  54
4.1.3 Log de Transações  57
4.2 Controle de Concorrência  59
4.2.1 Atualizações Perdidas  59
4.2.2 Dados não Consolidados  60
4.2.3 Recuperações Inconsistentes  61
4.2.4 Escalonador  63
4.3 Resumo  77

Cap. 5 - RECUPERAÇÃO  79
5.1 Conceitos de Recuperação  79
5.1.1 Esboço da recuperação e categorização dos algoritmos
de recuperação  79
5.1.2 Caching (buffering) de Blocos de Disco  81
5.2 Algoritmo de recuperação ARIES  83
5.3 Backup e recuperação de banco de dados contra
falhas catastróficas  84
5.4 Cold (Frio) e Hot (quente) backup  85
5.5 Backup e Restore no PostgreSQL  86
5.5.1 Backup de um banco (arquivo texto SQL):  86
5.5.2 Backup de um banco (pg_restore)  86
5.5.3 Restaurando backup texto (SQL) de um banco com o
psql  87
5.5.4 Restaurando backup compactado de um banco com o
pg_restore  87
5.5.5 Outros exemplos de backup em PostgreSQL  88

Cap. 6 - PERFORMANCE DO BANCO DE DADOS  89


6.1 Sintonização (tuning) de Desempenho: Cliente e
Servidor  91
6.2 Performance de Consultas - Cliente  92
6.2.1 Expressões Condicionais  95
6.3 Performance de SGBD - Servidor  97
6.3.1 Estatísticas de Banco de Dados  97
6.3.2 Processamento de Consultas  98
6.3.3 Índices e Otimização de Consultas  102
6.3.4 Escolhas de Otimizadores  105
6.3.5 Utilização de Sugestões (hints)  107
6.4 Performance no PostgreSQL  108
6.4.1 Explain  108
6.4.2 Atualizando as Estatísticas no PostgreSQL  110

REFERÊNCIAS  111
Análise e Comparação
de SGBD

Olá, Turma!
Neste capítulo, apresentaremos conceitos importantes que devem ser
objeto em uma análise ou comparação entre SGBD.
Os objetivos deste capítulo são:
• conhecer os conceitos para análise de um SGBD;
• compreender como podem ser feitas as comparações entre SGBD.

A análise e comparação do melhor sistema de gerenciador de banco


de dados começa com a análise das necessidades e características dos
bancos de dados. As necessidades de informações da organização
afetam o tipo de dado coletado e o tipo de sistema de gerenciamento
de banco de dados a ser usado. Características importantes dos bancos
de dados incluem seu tamanho, a quantidade de usuários simultâneos,
o desempenho, a capacidade do SGBD se integrar a outros sistemas, as
características do SGBD, considerações sobre os fornecedores e o custo
do sistema de gerenciamento x banco de dados (Stair e Reynolds, 2011).

Vamos ver cada um desses itens.

1.1 Tamanho da Base de Dados

O tamanho da base de dados depende de sua quantidade de registros ou


arquivos. O tamanho determina os requisitos gerais de armazenamento
para a base de dados. A maioria dos sistemas de gerenciador de bases
de dados pode manipular banco de dados relativamente pequenos,
com menos de 100 milhões de bytes; poucas podem gerenciar banco de
dados com até terabytes (TB) ou petabytes (PB).

Uma análise fácil seria: vamos então escolher um que possa trabalhar
com terabytes, independente do tamanho de meus bancos de dados.
Esta análise não está correta. O custo total do SGBD que pode
trabalhar com bases de terabytes será maior que o custo de SGBD
que trabalham com bases menores.
12
Prof. Eros Estevão de Moura

1.2 Quantidade de Usuários Simultâneos

A quantidade de usuários que podem acessar simultaneamente o


conteúdo da base de dados é também um fator importante. Obviamente,
uma base de dados usada por um grande grupo de trabalho deve
permitir acesso simultâneo eficaz; se não permitir, a eficiência dos
membros do grupo de trabalho será reduzida. O termo escalabilidade
é, por vezes, usado para descrever quão bem uma base de dados
funciona em função de seu tamanho ou da quantidade de usuários que
a acessam simultaneamente. Um sistema de gerenciamento de banco
de dados altamente escalável é desejável para conseguir flexibilidade.
Infelizmente, muitas companhias escolhem mal um SGBD quanto a
essa característica, e são então forçadas a passar para um novo SGBD
quando o original não atende a suas expectativas.

Antigamente era comum que o custo do SGBD tivesse associado ao


número de usuários. Com a possibilidade de se utilizar servidores de
aplicação, por exemplo, isso passou a não ser a forma mais comum
de comercialização. Isso é feito hoje em dia baseado na capacidade
do computador / sistema operacional onde será instalado o SGBD.

1.3 Desempenho

O quão rapidamente a base de dados pode atualizar registros pode ser


o critério de desempenho mais importante para algumas organizações.
Companhias de cartões de crédito e companhias aéreas, por exemplo,
devem ter SGBD que possam atualizar registros de clientes e verificar
crédito ou reservar uma passagem aérea em segundos, não em minutos.
Outras aplicações, como folha de pagamentos, podem ser efetuadas
uma vez por semana ou com frequência ainda menor e não exigem
processamento imediato. Se uma aplicação exigir processamento
imediato, ela também exigirá recursos para recuperação rápida no
caso de o sistema computacional interromper temporariamente seu
funcionamento. Outras considerações de desempenho são a quantidade
máxima de usuários simultâneos e o quanto de memória principal é
exigido para o programa de gerenciamento de banco de dados.

Observe que o SGBD pode ser o mais rápido do mundo, mas, se


sua query não estiver escrita da forma correta, você não terá a
performance que deseja.
13
Laboratório de Banco de Dados

1.4 Integração

Um aspecto-chave de qualquer sistema de gerenciamento de banco de


dados é a sua capacidade de se integrar com outras aplicações e bancos de
dados. Um determinante-chave aqui é que sistemas operacionais podem ser
usados como: Unix, Linux e Windows. Algumas companhias usam diversos
bancos de dados para diferentes aplicações em diferentes localizações. Uma
empresa com quatro fábricas em três estados distintos poderia ter uma
base de dados separada para cada fábrica. A capacidade de um programa
sistema gerenciador de banco de dados importar e exportar dados para
outras bancos de dados e aplicações pode ser uma consideração crítica.

1.5 Recursos

Os recursos do sistema de gerenciamento de bancos de dados podem


também fazer uma grande diferença. A maioria dos programas de
bancos de dados vem com procedimentos de segurança, proteção de
privacidade e diversas ferramentas. Outros recursos podem incluir
facilidade de uso do pacote de banco de dados e disponibilidade de
manuais e documentação para ajudar a organização a obter o máximo
do pacote de bancos de dados. Recursos adicionais, como serviços de
apoio e acompanhamento e exemplos de uso imediato, ajudam a facilitar
o uso do produto e são muito importantes.

De fato, a pressão para reduzir os orçamentos de sistemas de informação


e a escassez de administradores de bancos de dados experientes levaram
as organizações a exigir software de bancos de dados com recursos para
simplificar as tarefas de gerenciamento de banco de dados. Em resposta
a isso, o DB2, após a versão 8 da IBM, vem com a capacidade de alertar
os administradores de bancos de dados usando correio eletrônico,
serviços de mensagens ou dispositivos móveis quando um problema
está surgindo, como uma aplicação que necessita de mais memória
ou uma consulta de usuário que leva um tempo excessivo para gerar
resposta. O software DB2, então, recomenda os passos específicos para
resolver o problema. Em alguns casos, o software DB2 pode diagnosticar
o problema e tomar ação corretiva de maneira automatizada.

Em outra abordagem, para minimizar a carga de gerenciamento de


banco de dados, a Oracle permite a seus clientes terceirizar as atividades
de gerenciamento de banco de dados. Os clientes podem escolher ter o
software instalado e funcionando em sistemas Oracle em uma central
de dados Oracle ou ter a Oracle gerenciando o software instalado nos
sistemas do cliente (Stair e Reynolds, 2011).
14
Prof. Eros Estevão de Moura

1.6 O fornecedor

O tamanho, a reputação e a estabilidade financeira do fornecedor podem


também ser considerados ao adquirir um banco de dados. Alguns
fornecedores são respeitados na indústria de sistemas de informação
e têm uma grande equipe de suporte para assistência, se necessário.
Uma companhia de banco de dados bem estabelecida e financeiramente
segura tem maior probabilidade de se manter nos negócios.

A capacidade de a empresa fornecer suporte global para grandes


companhias multinacionais está se tornando cada vez mais importante.
A CERN, organização europeia para pesquisas nucleares localizada em
Geneva, na Suíça, está construindo um acelerador de partículas que
permitirá aos cientistas novas visões sobre a estrutura da matéria. Quando
essa instalação iniciar suas operações, em sua capacidade total, ela gerará
uma prodigiosa quantidade de informações entre 5 e 20 PB (petabytes) de
dados por ano. Em 2006, o pessoal de sistemas de informação da CERN
estava considerando o uso do Oracle9i em vez do software de bases de
dados Objectivity, até agora um padrão não oficial entre os laboratórios
de pesquisas nucleares. O motivo principal é que a Oracle tem extensas
operações na Europa, mas a Objectivity não, e sua sede fica a milhares de
quilômetros de distância, em Mountain View, na Califórnia.

1.7 O custo

Pacotes de banco de dados para computadores pessoais podem


custar poucos reais, mas os sistemas grandes de banco de dados
para computadores de grande porte podem custar muito caro. Além
do custo inicial do pacote de banco de dados, os custos mensais de
operações deveriam ser considerados, pois algumas companhias de
bancos de dados alugam seu software de bancos de dados. Os custos
mensais de aluguel, manutenção, hardware, software adicional e
pessoal podem ser substanciais.

1.8 Conclusão

A análise e a comparação de SGBD deve ser feita de forma a atender uma


determinada realidade, isso pois um SGBD muito bom para a empresa
X pode não ser a melhor opção para a empresa Y.
15
Laboratório de Banco de Dados

Eu tive a oportunidade de, junto com um colega de trabalho, analisar e


comparar SGBD para compra em uma grande empresa, assim avaliamos
algumas características de vários SGBD. As características escolhidas
eram particulares à empresa onde trabalhávamos. Por exemplo: essa
empresa existe em praticamente todo Brasil, daí a característica de como
o SGBD trabalhava com a distribuição de dados, através da replicação de
dados, para nós era muito importante. Por isso essa característica, além
de ser observada, recebeu um peso maior do que outras características.

Se estivesse em um banco, a característica de segurança seria


obviamente observada e certamente receberia um peso maior que
outras características.

Em sala de aula, costumo fazer um comentário sobre a escolha de


um SGBD para uma empresa. É possível colocar um SGBD Oracle
na padaria da esquina? Sim, é possível, mas a questão é, seria a
melhor escolha? Muito provavelmente não.

Faça uma pesquisa e defina qual SGBD você escolheria para cada
uma dessas empresas:
a) uma mercearia pequena do bairro;
b) uma pequena locadora de carros com três filiais que quer
que seu sistema funcione na WEB;
c) uma grande empresa do ramo de logística, com várias
filiais espalhadas pelo Brasil. Leve em conta a necessidade das
informações estarem disponíveis nas filiais.
16
Prof. Eros Estevão de Moura
SQL Avançado

Olá, Turma!
Neste capítulo, daremos prosseguimento ao que já aprendemos
sobre SQL na disciplina de Banco de Dados. Estaremos vendo mais
algumas coisas que podemos fazer no SGBD.
Os objetivos deste capítulo são:
• conhecer a store procedure;
• conhecer o trigger;
• compreender a utilização de views;

2.1 Store Procedure ou Procedimento


Armazenado

Procedimentos armazenados são programas que ficam armazenados


dentro do SGBD. Normalmente, estaremos utilizando store procedures
com objetivo de performance. A opção pela store procedure por
questões de performance deve estar associada a um processo que tem
a característica de ler muitos dados. Neste caso, já há um ganho, pois
estes dados, se estivessem sendo executados na aplicação, acarretaria
que teriam que chegar à aplicação via rede, gerando tráfego e tempo a
mais para o acesso aos dados. Há ainda outro objetivo, muito menos
frequente, para utilização de store procedure: é um processo complicado
e se deseja “esconder” este procedimento (encapsulamento) ou o
administrador de banco de dados deseja estabelecer um melhor método
para acesso a um conjunto de dados. Neste caso, o analista/programador
não acessaria diretamente as tabelas e sim a store procedure.

Conceitualmente, uma procedure não retorna ou não tem a


obrigação de retornar nada. Já as functions sempre retornam
alguma coisa.

Criada a store procedure, a aplicação manda executar. Após o final


do processamento, a aplicação recebe o retorno da store procedure. A
sintaxe da criação da store procedure não tem um padrão nos SGBD. No
18
Prof. Eros Estevão de Moura

caso do PostgreSQL, vamos ver mais detalhes a seguir, a store procedure


será implementada através de uma função.

Características:

• são procedimentos armazenados no SGBD;

• constituem objetos do SGBD;

• são escritos em linguagens procedurais (normalmente há uma


linguagem proprietária do SGBD) ou outras linguagens, como C,
C# ou Java (dependendo do SGBD);

• podem receber parâmetros;

• podem chamar outras Procedures;

• podem retornar valores para os objetos chamadores;

• podem ser chamadas remotamente;

• são objetos compilados e armazenados;

• podem incluir transações;

• podem ser simples ou complexos;

A maioria dos SGBD’s disponíveis no mercado implementam Stored


Procedures, a exemplo do Oracle e PostgreSQL.

Como mencionei, o PostgreSQL implementa a store procedure através


do uso de function. Vamos ver um exemplo simples de store procedure:

CREATE OR REPLACE FUNCTION lista_cidade()

RETURNS setof cidades AS

‘select * from cidades;’

LANGUAGE ‘sql’;

no qual:

 CREATE OR REPLACE FUNCTION: cria (se não existir) ou


recria (caso ela já exista) a função;

 lista_cidade() : nome da função (store procedure no PostgreSQL)


19
Laboratório de Banco de Dados

 RETURNS setof cidades AS: retorno da função (setof retorna


um conjunto formado pela mesma estrutura da tabela, neste caso,
cidades)

 'select * from cidades;' : o corpo do código da função que deve


ser compatível com o parâmetro LANGUAGE.

 LANGUAGE 'sql' : a linguagem que está sendo utilizada nesta


função, neste caso SQL.

2.1.1 A sintaxe da simplificada da store procedure no


PostgreSQL

onde:

 Nome - é o nome da função a ser criada.

 Tipo - define o tipo do argumento que será recebido.

 Tipo_retorno - é o tipo de dado que será retornado pela nossa


função.

 Nome_linguagem - é o nome da linguagem que será utilizada


para escrever a nossa função.

 Conteudo - é o corpo da nossa função.

Exemplo:

2.1.2 Como utilizar store procedure no PostgreSQL

Para utilizar a store procedure (função) no PostgreSQL basta, por


exemplo, chamá-la em um comando select

Exemplo:

Neste caso foram passados 2 parâmetros (2 e 3). Será apresentado como


resposta o número 5.
20
Prof. Eros Estevão de Moura

2.1.3 Como apagar uma store procedure no PostgreSQL

Para apagar uma store procedure (função) no PostgreSQL, basta executar


o comando DROP FUNCTION.

Exemplo:

DROP FUNCTION soma(integer,integer);

Observe a necessidade de colocar também os parâmetros da store


procedure (função).

2.1.4 A linguagem PL/pgSQL

A PL/pgSQL é uma linguagem estrutural estendida da SQL proprietária


do PostgreSQL que tem por objetivo auxiliar as tarefas de programação.

Ela incorpora à SQL características procedurais, como os benefícios e


facilidades de controle de fluxo de programas que as melhores linguagens
possuem. Por exemplo, loops estruturados (for, while) e controle de
decisão (if then else).

A PL/pgSQL é estruturada em blocos, assim, todo o texto de definição de


uma função precisa estar em um bloco. Os blocos possuem a seguinte sintaxe:

em que:

$$: inicia a função em PL/pgSQL;

DECLARE: é a área para declaração de variáveis. As variáveis declaradas


nessa sessão são inicializadas recebendo seus valores default sempre que
existe uma entrada nesse bloco. Como na maior parte das linguagens
existentes, na PL/pgSQL, variáveis com o mesmo nome possuem o seu
escopo definido para o bloco imediatamente posterior à sua declaração;
21
Laboratório de Banco de Dados

BEGIN: início do bloco do código em PL/pgSQL;

END: final do bloco do código em PL/pgSQL;

Observações:

Esse pequeno exemplo serve também para exemplificar como, no PL/


pgSQL, é feito o controle de escopo das variáveis.

Essas informações sobre PL/pgSQL são apenas iniciais. Se você deseja


programar nesta linguagem para criar store procedures e/ou triggers
em PostgreSQL, sugiro a leitura do manual que pode ser encontrado
em www.postgresql.org/docs/9.0/interactive/index.html.

2.2 Trigger ou gatilho

Triggers, também chamado de gatilhos, são tipos especiais de


procedimento armazenado, que são executados automaticamente pelo
SGBD baseado em um conjunto de eventos que podem ser INSERT,
UPDATE e/ou DELETE em uma tabela do banco de dados.

Características:

• são procedimentos armazenados no SGBD;

• são criados como objetos no SGBD;

• são tipos especiais de Procedures, mas não podem receber


parâmetros;

• estão vinculados a tabelas especificas;


22
Prof. Eros Estevão de Moura

• deve-se tomar cuidado para não criar recursividade dentro do trigger.


Quando um gatilho executa comandos SQL, esses comandos podem
disparar gatilhos novamente, o que é conhecido como cascatear gatilhos.
Não existe limitação direta do número de níveis de cascateamento. É
possível que o cascateamento cause chamadas recursivas do mesmo
gatilho;

• dentro do corpo de um trigger pode haver comandos DML,


estruturas de controle, chamada a outros procedimentos, etc.;

• não se pode usar em um trigger: Comandos DDL;

• são chamados automaticamente;

• não podem ser chamados diretamente;

• são partes de uma transação;

São exemplos de aplicações dos Gatilhos:

• alterações em cascata, em tabelas relacionadas de um banco de


dados;

• imposição de uma integridade de dados mais complexa do que


uma restrição CHECK;

• manutenção de dados desnormalizados ;

• comparação dos estados anteriores e posteriores dos dados que


estão sendo modificados;

2.2.1 Antes (BEFORE) ou após (AFTER)

O gatilho pode ser especificado para disparar:

 antes (BEFORE) da operação ser realizada no registro (antes


das restrições serem verificadas e o INSERT, UPDATE ou DELETE
serem efetuados); ou

 após (AFTER) a operação ser realizada (ou seja, após as restrições


serem verificadas e o INSERT, UPDATE ou DELETE ter sido
efetivado).

Se o gatilho disparar antes do evento, o gatilho pode evitar a operação


para o registro atual, ou modificar o registro sendo inserido (para as
operações de INSERT e UPDATE somente).

Se o gatilho disparar após o evento todas as modificações, incluindo a


última inserção, atualização ou exclusão, são “visíveis” para o gatilho.
23
Laboratório de Banco de Dados

2.2.2 Para um registro ou para um comando

O gatilho pode ser especificado para dispara:

 a cada registro afetado (ROW);

 a cada comando (STATEMENT).

Exemplo:

Vamos imaginar que há um gatilho criado para tabela cliente.

Eu faço o seguinte comando SQL (DML)

Imaginando que existe a coluna limite na tabela cliente e que esta tabela
possui 1000 clientes, este comando afetará 1000 registros.

Se o meu gatilho é do tipo ROW ele será disparado 1000 vezes;

Se o meu gatilho é do tipo STATEMENT ele será disparado apenas uma vez;

2.2.3 Sintaxe do trigger no PostgreSQL

Onde:

 Nome_trigger: o nome do gatilho (trigger);

BEFORE | AFTER: antes ou depois da confirmação da operação;


 

  evento [OR ...]: INSERT e/ou UPDATE e/ou DELETE: por


exemplo: INSERT, outro exemplo INSERT OR UPDATE;

Tabela: O nome de uma tabela existente;


 

 FOR EACH { ROW | STATEMENT }: para cada registro afetado


(ROW) para cada comando (STATEMENT);

  função ( argumentos ): uma função fornecida pelo usuário que


já deve estar criada;
24
Prof. Eros Estevão de Moura

2.2.4 Um exemplo de gatilho no PostgreSQL

Vamos criar um trigger muito comum. Um trigger para gerar um


histórico de alterações que ocorreram em uma tabela.

A DDL (Data Definition Language), ou Linguagem de Definição


de Dados, é um grupo de comandos da linguagem SQL responsável
pela definição dos dados, ou seja, pela criação de bancos, esquemas,
tabelas, campos, tipos de dados, constraints, etc,

O trigger do exemplo será criado para uma tabela chamada cliente.

A DDL da tabela cliente:

A DDL da tabela que terá o histórico de alterações, também chamado


de log:

Agora, vamos criar a store procedure (function) que será chamada


quando o trigger for disparado:
25
Laboratório de Banco de Dados

Observações:

 now(): é uma função do PostgreSQL que retorna a data e hora


do momento;

 user: retorna o usuário logado no momento;

 TG_OP: retorna a operação que está sendo executada no


momento (INSERT, UPDATE ou DELETE),

 RETURN new; : retorna sem fechar a transação (veremos mais a


frente sobre transação)

Com a store procedure (função) cria, basta agora criamos o trigger:

Este gatilho (trigger) tem o nome tg_cliente, será disparado antes da


efetivação da transação, sempre que ocorrer um INSERT ou um
UPDATE ou um DELETE na tabela Cliente para cada registro que for
afetado.

2.2.5 Teste do gatilho (trigger)

Com o gatilho (trigger) criado, farei o seguinte comando DML:

Com este comando, todos os cliente receberão o nome Teste. Se existirem


1000 clientes, os 1000 terão o mesmo nome: Teste.

Com o trigger é possível afirmar que a tabela log receberá 1000 registros,

indicando a data e hora da operação, meu usuário e a operação UPDATE.

Outro teste:
26
Prof. Eros Estevão de Moura

2.3 Apagando um gatilho (trigger)

Para apagar um Trigger

Onde:

 <nome_trigger>: é o nome do gatilho (trigger);

 <tabela>: nome da tabela onde o trigger(gatilho) foi criado;

2.3.1 Exemplo para apagar um gatilho (trigger)

DROP TRIGGER tg_cliente ON cliente;

2.4 Um pouco mais sobre visões (views)

Já tivemos contato com visão na disciplina de banco de dados. Vamos


reforçar um pouco mais o que é para que usar uma visão (view). Uma
visão é forma de disponibilizar, para um ou mais usuários, uma porção
do banco de dados. Os objetivos para fazer isso podem ser:

 transformar uma query complexa (JOINS, GROUP BY, HAVING,


etc) em uma query simples (SELECT * FROM VISÃO);

 uma forma de filtrar por coluna, ou seja, mostrar os campos que


devem ser mostrados para um ou mais usuários. A coluna está na
tabela, mas o usuário só vê o que deve ver;

 esta última pode estar associado a questões de segurança;

 o DBA (administrador de banco de dados) pode usar uma visão


para criar uma forma mais performática de acesso a determinados
dados, principalmente quando a equipe de analista de sistemas não
tem muito conhecimento de SQL;

A visão pode ser criada a partir de um comando SELECT, ou seja, ela


pode fazer uso de uma ou mais tabela, de todas ou apenas algumas
colunas dessas tabelas.

Como ela é apenas o resultado de um comando SELECT, ela não possui


dados (os dados estão nas tabelas que o comando SELECT utilizou), por
isso pode ser chamada de tabela virtual.
27
Laboratório de Banco de Dados

Alguns SGBD permitem alterar os dados das tabelas através das visões
(views) e outros não. No PostgreSQL isso não é permitido. As visões são
apenas para leitura.

Em (Silberschattz, 2006) define visão como qualquer relação (tabela)


que não seja parte do modelo lógico, mas que se torna visível a um
usuário como uma relação (tabela) virtual, denomina-se view (visão).

Criamos uma visão em SQL por meio do comando CREATE VIEW.


Para definir uma visão, precisamos dar a ela um nome (nome da visão)
e definir a consulta que a processa.

2.4.1 Sintaxe para criação de visão em SQL

Onde:

<nome_da_visao>: nome da visão (view);

<comando SELECT>: qualquer consulta SQL válida.

Como exemplo, vamos criar uma visão (view) com um filtro de registro
e coluna. Quando faço um filtro de registro, isso quer dizer que nem
todos os registros estarão disponíveis. Quando faço um filtro por coluna,
estou dizendo que nem todas as colunas estarão disponíveis.

Neste caso, desejamos disponibilizar para os setores o nome, telefone


fixo e celular dos funcionários da área comercial. Apenas para área
comercial e apenas os dados listados.

2.4.2 Como utilizar uma visão (view)

Para utilizar uma visão (view):


28
Prof. Eros Estevão de Moura

2.4.3 Uso avançado de visões (views)

Imagine uma situação em que você precisasse de uma visão apenas para
conseguir fazer uma query e apenas para quando a sua query fosse ser
executada. Você pode criar a visão e deixar no banco de dados, mas esta
visão que você quer criar é apenas parte da solução, ou seja, ela ainda
não retorna nenhuma informação que seja produtiva.

Há uma forma de você criar “visões temporárias” dentro de uma query,


com objetivo de simplificar uma query complexa, dividindo um grande
problema em problemas menores.

Como uma visão é o resultado de um SELECT, podemos dar um nome


a um resultado de um comando SELECT, quando isso for útil.

Vamos primeiro fazer um exercício. Veja a query abaixo:

Você conseguiu entender essa query?

Isso é apenas para exemplificar o fato de que você pode nomear,


através de um apelido, um resultado de um comando SELECT dentro
de outro SELECT.

O SELECT mais interno “SELECT * FROM cinema c” recebeu um


apelido “v1” (vermelha); essa query está sendo acessada pelo comando
SELECT mais externo, comando “SELECT * FROM (SELECT * FROM
cinema c) v1” verde.

Outra forma de fazer este mesmo comando seria criar uma visão com
o nome v1
29
Laboratório de Banco de Dados

E depois fazer

O que foi feito, na verdade, foi dar um nome para o resultado do comando
“SELECT * FROM cinema c”. Depois de dar um nome (apelido),
podemos acessar esse resultado como se fosse uma visão criada antes
do comando.

Isso pode parecer que não serve para nada, mas quando essa query que
você quer dar um nome tiver uma ou mais folhas de código SQL, você
pode querer testar apenas essa query interna. Quando o resultado dela for
o esperado, você pode fazer um JOIN com as outras tabelas da sua query.

Assim, você pode quebrar uma query muito complicada em queries


menores. Isso, provavelmente, tornará o trabalho mais fácil.

2.5 Como criar um banco de dados no


PostgreSQL

Nem sempre você terá disponível uma ferramenta gráfica para trabalhar.
Em sistemas operacionais Linux, configurados para trabalhar como
servidores (por exemplo, servidor de banco de dados), é muito comum
não instalar a parte gráfica do sistema operacional, buscando melhor
performance.

Por este motivo, vamos dar uma olhada na sintaxe para criar uma banco
de dados no PostgreSQL.

Onde:

 nome_banco: o nome do banco de dados a ser criado.

 caminho: um local alternativo no sistema de arquivos onde será


armazenado o banco de dados, especificado como uma cadeia de
caracteres; ou DEFAULT/não informar parâmetro para utilizar o
local padrão.

 gabarito: nome do banco de dados a ser usado como gabarito


30
Prof. Eros Estevão de Moura

para a criação do novo banco de dados, ou DEFAULT/não informar


parâmetro para utilizar o banco de dados de gabarito padrão
(template1).

 codificação: método de codificação multibyte a ser utilizado no


novo banco de dados. Especifique o nome como uma cadeia de
caracteres (por exemplo, 'SQL_ASCII', 'UTF8'), ou o número inteiro
da codificação, ou DEFAULT para utilizar a codificação padrão.

Exemplos:

2.6 Como apagar um banco de dados no


PostgreSQL

Vamos dar uma olhada na sintaxe para apagar um banco de dados no


PostgreSQL.

Onde:

nome_banco: O nome do banco de dados existente a ser removido


 

Exemplo:

DROP DATABASE db_outrolugar;


SQL na prática

Vamos lá!
Agora vamos praticar nossos conhecimentos de SQL.
Os objetivos deste capítulo são:
  demonstrar os conhecimentos adquiridos da linguagem SQL.

3.1 Estudo de Caso 1

Vamos imaginar que você está trabalhando em uma empresa de telefonia.


Algumas das tabelas do banco de dados com que você trabalha estão
apresentadas abaixo.
32
Prof. Eros Estevão de Moura
33
Laboratório de Banco de Dados

Surgiram algumas necessidades, listadas logo abaixo, que você deve


resolver.

1. Há uma necessidade de se fazer algumas estatísticas por UF. Se


deseja uma listagem que contenha: nome da UF, a quantidade de
chamadas por UF, a soma do valor da chamada por UF, a média
aritmética do valor da chamada por UF, o menor valor de chamada
em cada UF e o maior valor de chamada por UF. Estas estatísticas
devem ser apenas para clientes do sexo masculino e só devem
aparecer nesta listagem as UF que a soma do valor da chama for
maior que 3. A listagem deve sair ordenada pelo maior valor de cada
UF. Faça a query para esta listagem.

2. Há muitas reclamações dos clientes. Para tentar verificar o


tamanho do problema, foi solicitado que fosse feita uma listagem
com a quantidade de chamadas contestadas por dia e a soma do
desconto também por dia. Só devem ser levadas em conta, chamadas
que o valor for maior que 2 e só devem aparecer os dias que tiveram
mais de 1 chamada contestada. Esta listagem deve sair em ordem
decrescente por data. Dar a resposta com a forma “antiga” e “nova”
com relação aos Joins.

3. Vai haver uma reunião e se deseja fazer uma listagem com a


quantidade total e soma total das chamadas que ocorreram no mês
de novembro de 2011 (01/11/2011 a 30/11/2011), mas só devem ser
levadas em conta as chamadas nas quais o tempo da chamada foi
maior do que 3, sendo que a listagem só deve sair se houver mais de
100 chamadas no período. Utilizar o operador BETWEEN.

4.Já existe a função gera_log() . Você deseja que, ao se alterar e deletar


na tabela cliente, mesmo sem saber se a operação terá sucesso, seja
disparada a função gera_log(). Também se deseja que, ao se inserir
na tabela cliente, mas apenas se tivermos certeza de que a operação
ocorreu com sucesso, que a função gera_log() seja disparada. Fazer
o(s) comando(s) para implementar estas necessidades.
34
Prof. Eros Estevão de Moura

5.Deseja-se uma listagem de TODAS as descrições de reclamações


e a soma dos descontos dados de cada descrição. No caso de uma
descrição não ter nenhum desconto, deve aparecer a descrição e
nenhum valor na soma (em branco). Fazer do estilo “novo”. (OUTER
JOIN etc)

3.2 Estudo de Caso 2

Vamos imaginar que você está trabalhando em um restaurante. Algumas


das tabelas do banco de dados com que você trabalha estão apresentadas
abaixo.
35
Laboratório de Banco de Dados
36
Prof. Eros Estevão de Moura
37
Laboratório de Banco de Dados
38
Prof. Eros Estevão de Moura

Surgiram algumas necessidades, listadas logo abaixo, que você deve


resolver.

1. o dono do restaurante deseja verificar a produtividade dos


produtos de seu restaurante. Para isso, solicitou a você uma listagem
que tivesse: nome do produto, a quantidade de pedidos feitos, a
maior quantidade vendida em uma só comanda, a menor quantidade
vendida em uma só comanda, a média pedida nas comandas. Ele só
deseja que saia nesta listagem os produtos cuja média da quantidade
seja maior que 10 e a categoria do produto seja LIQUIDO. Esta
listagem deve sair em ordem decrescente pela média da quantidade;

2. 0 dono do restaurante deseja saber se vale a pena continuar com


a quantidade de mesas que o restaurante tem atualmente. Para isso,
solicitou a você uma listagem que contenha: a descrição da mesa e
a soma total de cada produto vendido em cada mesa(usar o nome
SOMA) (não utilizar o total da comanda). Nesta listagem, devem
aparecer apenas as mesas com o código 1,2,3 e 4 (utilizar a cláusula
IN) e só devem ser computados as vendas que foram pagas com o
tipo de pagamento DINHEIRO. Ele ainda solicitou que só saíssem
na listagem os produtos que foram vendidos mais de 10 itens de
comanda e que a listagem saísse em ordem da soma;

3. o dono do restaurante agora deseja verificar se deve ficar com


a quantidade de garçons que ele possui hoje. Esta verificação será
feita pela quantidade de comandas (e não de itens de comanda) que
cada garçom atende. Para isto, ele solicitou uma listagem contendo
o nome do garçom e a quantidade de comandas atendidas por ele
(deve sair quantidade_comandas). Nesta listagem só devem sair os
garçons e para isso se deve utilizar o nome do cargo com todos os
cargos que começam com a letra G. A listagem deve sair ordenada
pela quantidade de comandas do maior para o menor. Fazer do jeito
“novo” e, se for o caso, em mais de uma forma;

4. já existem duas funções: uma que soma o valor do produto no


campo valor_total_consumo na tabela conta e uma outra que
subtrai um valor do produto no mesmo campo. Você deseja que
esta soma e a subtração sejam feitas de forma automática: a soma
deverá acontecer de forma automática quando houve uma inclusão
de um item de comanda com a utilização da função f_soma_valor;
a subtração deverá ocorrer de forma automática quando houver
uma exclusão de um item de comanda com a utilização da função
f_subtrai_valor. Faça o código para implementar esta solução.
39
Laboratório de Banco de Dados

3.3 Estudo de Caso 3

Vamos imaginar que você está trabalhando em uma locadora. Algumas


das tabelas do banco de dados com que você trabalha estão apresentadas
abaixo.
40
Prof. Eros Estevão de Moura

Surgiram algumas necessidades, listadas logo abaixo, que você deve


resolver.

1. O dono da locadora deseja saber quais os clientes que alugaram


mais quantidade de filmes. Para isso, solicitou uma listagem com
o nome de cada cliente e a quantidade total de locações de cada
cliente(dar o nome-quantidade), ordenado do cliente com mais
locações até o cliente com menos locações. Só devem aparecer nesta
listagem clientes com mais de 10 locações e que moram na cidade
Cachoeiro de Itapemirim.

2. O dono da locadora deseja saber qual o gênero de filme que dá


mais retorno a sua locadora, para isto solicitou uma listagem de
cada nome de gênero de filme informando qual o maior valor de
locação de cada gênero, o menor valor de locação de cada gênero,
a média do valor de locação de cada gênero, a soma de locações
de cada gênero e a quantidade de locações de cada gênero. Estas
informações são relativas a cada gênero do filme locado. Só devem
aparecer nesta listagem filmes cujo valor pago na compra pelo filme
41
Laboratório de Banco de Dados

(valor_compra na tabela filme) é maior que 100 reais e a quantidade


locações do gênero for menor que 1000. Ele solicitou, ainda, que
a mesma fosse impressa, ordenada de forma decrescente pela
quantidade de locações de cada gênero de filme.

3. O dono da locadora deseja saber quais são os estados (UF) dos


clientes que mais fazem locações em sua locadora. Não interessa
para o dono da locadora as locações com valor unitário menor que
2 reais, e apenas para o nome da cidade onde o cliente mora que
começar com a letra ‘C’ e somente para as seguintes UF onde o
cliente mora: RJ, SP, ES, MG, BA e PE (utilizar a cláusula IN). Ele
quer que seja listado: Nome da UF , Soma total de Locações e Valor
Médio das Locações, ordenados por Nome da UF.

4. O diretor da locadora quer que os funcionários F15 e F16 do


Departamento Comercial possam acessar os dados das locações
(todas as permissões), mas sem a informação do valor da locação
(valor_locacao na tabela locação) e apenas os clientes que moram
em Cachoeiro de Itapemirim. OBS: hoje estes funcionários têm
acesso para tudo na tabela Locação.

5. O diretor da empresa está preocupado com o acesso às


informações do banco de dados, em especial à tabela cliente. A
empresa possui 3 departamentos, sendo: operacional, financeiro
e comercial. Ele deseja que o departamento operacional possa ler,
alterar, incluir e excluir na tabela cliente, já o financeiro poderá
ler e alterar e o comercial apenas ler na tabela cliente. Cada um
desses departamentos possue 2 funcionários, sendo: F1 e F2 do
operacional, F3 e F4 do financeiro e o F5 e F6 do comercial. Há
planos desta empresa aumentar muito o número de empregados.
Como você resolveria esta necessidade, levando em conta a previsão
de crescimento da empresa? Observação: os funcionários ainda não
têm login no banco de dados e eles devem ter a possibilidade de
logar no banco de dados com a senha inicial 123. Por último, não
utilizar ALL.

3.4 Estudo de Caso 4

Vamos imaginar que você está trabalhando em uma assistência técnica


de computadores. Algumas das tabelas do banco de dados com que você
trabalha estão apresentadas abaixo.
42
Prof. Eros Estevão de Moura
43
Laboratório de Banco de Dados
44
Prof. Eros Estevão de Moura

Surgiram algumas necessidades, listadas logo abaixo, que você deve


resolver.

1. O diretor da empresa quer obter algumas informações sobre


a produtividade da empresa. Ele solicitou o total recebido pela
empresa em cada serviço (que é o valor cobrado do cliente), a
quantidade de serviços executados, a média cobrada de cada serviço
e o maior valor cobrado de cada serviço, o menor valor cobrado
de cada serviço. O resultado deve possuir a descrição do serviço e
o nome de cada resultado deve ser: nome_servico, total_recebido,
quantidade_servicos, media_cobrada, maior_valor e menor_valor.
Utilizar o valor recebido em cada serviço e não pelo total da OS.
Só devem ser considerados os serviços cuja estimativa de tempo é
menor que 100 e os totais de serviços que forem menores que 1000.

2. O gerente que cuida do estoque quer saber, em média, qual é a


utilização do estoque em cada Ordem de serviço. Para obter estar
informação, ele solicitou a soma da quantidade utilizada dos itens do
estoque em cada Ordem de Serviço, ordenada de forma decrescente
pela quantidade. (Mostrar a descrição do item do estoque e não seu
código). Listar em ordem decrescente por quantidade utilizada.

3. Com o objetivo de verificar o desconto que foi dado em cada


Ordem de Serviço por cada técnico, deseja-se uma listagem com o
nome do técnico, o total do valor cobrado em cada serviço por este
técnico e o total do valor do serviço (valor da tabela de serviços)
45
Laboratório de Banco de Dados

dos serviços que ele fez. Apenas se deve utilizar os serviços em que
foram cobrados valores com desconto, ou seja, serviços no qual o
valor cobrado é menor que o valor da tabela.

4. O diretor da empresa quer que os funcionários F5 e F6 do


Departamento Comercial possam acessar os dados das ordens de
serviço, mas sem a informação do valor total da OS (valor_total_os)
e apenas as ordens de serviço que já estejam baixadas, ou seja, a
posicao_os é igual a B. Resolva esta necessidade.

5. O diretor da empresa está preocupado com o acesso as informações


do banco de dados, em especial a tabela servico_executado. A
empresa possui 3 departamentos, sendo: operacional, financeiro
e comercial. Ele deseja que o departamento operacional possa ler,
alterar, incluir e excluir na tabela servico_executado, já o financeiro
poderá ler e alterar e o comercial apenas ler na tabela servico_
executado. Cada um desses departamentos possue 2 funcionários,
sendo: F1 e F2 do operacional, F3 e F4 do financeiro e o F5 e F6
do comercial. Há planos desta empresa aumentar muito o número
de empregados. Como você resolveria esta necessidade, levando
em conta a previsão de crescimento da empresa? Observação: os
funcionários ainda não têm login no banco de dados.

6. O diretor da empresa quer saber se vale a pena trabalhar com


o número de atendentes atuais. Para chegar a esta conclusão, ele
solicitou uma listagem em que possa associar as Ordens de Serviços
que cada atendente abriu com os serviços executados em cada
uma dessas OS. Esta listagem deve conter o nome das atendentes,
a quantidade de serviços e a soma dos valores cobrados em cada
serviço (o valor que está na tabela servico_executado), mas apenas
devem sair nesta relação as atendentes que tiveram menos de 10
serviços associados.

3.5 Estudo de Caso 5

Vamos imaginar que você está trabalhando em uma empresa de ônibus


interestadual. Algumas das tabelas do banco de dados com que você
trabalha estão apresentadas abaixo.
46
Prof. Eros Estevão de Moura
47
Laboratório de Banco de Dados
48
Prof. Eros Estevão de Moura

Surgiram algumas necessidades, listadas logo abaixo, que você deve


resolver.

1. Listar com estas informações: o nome do motorista e a quantidade


de viagens que fez, ordenado por quem fez mais para quem fez
menos (a informação de quantidade deve ter este nome).

2. Listar o nome e a quantidade de viagens de cada origem das


passagens, ordenado por quantidade.

3. O valor médio, com o menor valor, a de maior valor e o total da


soma das passagens de cada tipo de ônibus (listar o nome e não o
código), ordenado decrescente pelo valor médio da passagem.

4. Você não tem problemas com a equipe de desenvolvimento e foi


solicitado a você que criasse uma maneira para que o departamento
operacional pudesse ver as passagens que estão cadastradas na tabela
passagem, mas não se deseja que este departamento veja o valor da
passagem, apenas as outras informações. Coloque o código de sua
solução e inclua um exemplo de como o departamento operacional
irá utilizar a solução.

3.6 Estudo de Caso 6

Vamos imaginar que você está trabalhando em um portal que presta


serviço a várias empresas do ramo de rochas ornamentais. Algumas das
tabelas do banco de dados com que você trabalha estão apresentadas
abaixo.
49
Laboratório de Banco de Dados
50
Prof. Eros Estevão de Moura
51
Laboratório de Banco de Dados

Surgiram algumas necessidades, listadas logo abaixo, que você deve


resolver.

1. O dono da empresa quer aumentar em 25% o valor de venda das


rochas que são extraídas do nome da UF São Paulo (ele não quer
fazer pela sigla da UF e sim pelo nome da UF; para aumentar em
25% basta multiplicar por 1.25).

2. O dono da empresa quer aumentar em 5% o valor da venda das


rochas que são compradas de todas as empresas que são da UF Rio
de Janeiro (ele não quer fazer pela sigla da UF e sim pelo nome da
UF).

3. O dono da empresa quer tirar do seu catálogo todas as rochas cuja


cor do Tipo da Rocha é Preta.

4. O dono da empresa solicitou que incluíssemos uma nova rocha


“Super Lilás” em seu cadastro. Esta rocha é de um novo tipo
(“Especial”), de uma nova cor (“Lilás”). O tipo da rocha “Especial”
também possui uma cor nova (“Lilás Opaco”). A empresa que vende
a rocha “Super Lilás” é a empresa “Rochas Tec” e também não é
cadastrada. Tanto a Rocha “Super Lilás” quanto a empresa “Rochas
Tec” são da Cidade de “Caparaó” e esta cidade está situada na UF que
tem o nome de “Minas Gerais”. A empresa não tem em seu cadastro
a Cidade de “Caparaó” e também não possui em seu cadastro a
UF “Minas Gerais”. O Local de Extração da Rocha “Super Lilás” é
“Pedreira Caparaó”. Depois de incluir, altere o valor da compra da
rocha para 100 e depois exclua a rocha “Super Lilás”.

Observações:

a. Os valores para os atributos não mencionados podem ser qualquer


um, desde que sejam válidos.

b. As operações devem ser feitas na ordem correta.


52
Prof. Eros Estevão de Moura
Transações e Acesso
Concorrente

Olá!
Neste capítulo, serão apresentados conceitos de transações e de
acesso concorrente. Estes dois assuntos são muito importantes
quando se trabalha com banco de dados. Há profissionais na área
de desenvolvimento de sistemas que, por falta de conhecimento, não
fazem bom uso dessa característica importante dos SGBD. Espero
que você possa compreender como utilizar transações da melhor
forma possível.
Os objetivos desse capítulo são aprender:
  sobre transações de bancos de dados e suas propriedades;
  o que é controle de concorrência e que papel ele executa na
manutenção da integridade dos bancos de dados;
  o que são métodos de bloqueio e como funcionam;
 como os métodos de time stamping são utilizados para
controle de concorrência;
  como os métodos otimistas são utilizados para controle de
concorrência.
Bom estudo!
Prof. Eros

4.1 A Transação

Segundo (Elmasri e Navathe, 2011), uma transação é uma unidade


atômica de trabalho, que deve ser concluída totalmente ou não ser feita
de forma alguma. Isso pode ser dito de outra maneira: o princípio do
tudo ou nada. Quando Navathe menciona unidade atômica, ele está se
referindo ao fato da transação não ter divisão. Em sala de aula, costumo
utilizar a seguinte definição: unidade lógica de trabalho, compreendendo
unidade como uma coisa única.

Transação: unidade lógica de trabalho


54
Prof. Eros Estevão de Moura

4.1.1 Exemplo do uso da transação

Acho que todos nós já vimos uma nota fiscal, certo? Podemos dividir a
nota fiscal em duas partes: um cabeçalho (nome do cliente, endereço,
telefone, etc.) e uma parte dos produtos comprados (código do produto,
descrição do produto, quantidade do produto, valor unitário, valor total
do item, etc.) que vai possuir uma linha para cada produto comprado.

Ao se desenvolver um programa para criar essa nota fiscal, uma pergunta


pode ser feita: adianta eu conseguir guardar no banco de dados a parte do
cabeçalho da nota fiscal e não conseguir guardar a parte dos produtos ou,
adianta, eu guardar a parte dos produtos e não conseguir guardar a parte
do cabeçalho? Não! Uma nota fiscal só pode ser válida se conseguirmos
guardar no banco de dados as duas partes: cabeçalho e produtos.

Se você não estiver trabalhando com um SGBD ou se você não sabe


utilizar transação em um SGBD, você terá que fazer um controle interno
no seu programa (passível de erro) para verificar se as duas partes foram
armazenadas corretamente. Apenas para lembrar que, no caso da nota
fiscal, teríamos duas tabelas no banco de dados.

Se você está utilizando um SGBD e conhece transação, vai entender que,


embora envolva duas tabelas, logicamente, é apenas uma coisa: ou eu gravo
a nota fiscal toda ou não gravo nada. Este é um exemplo de uma transação.

4.1.2 Propriedades das Transações

Segundo (Rob e Coronel, 2011), toda transação individual deve


apresentar indivisibilidade, consistência, isolamento e durabilidade.
Além disso, ao executar várias transações, o SGBD deve escalonar
a execução concorrente de suas operações. O escalonamento dessas
operações de transação deve apresentar a propriedade de ser serializável.
Vejamos brevemente cada uma dessas propriedades.

 A indivisibilidade exige que todas as operações (solicitações


de SQL) de uma transação estejam concluídas. Caso contrário, a
transação é abortada. Se uma transação Tl tiver quatro solicitações
de SQL, todas devem ser concluídas com sucesso, senão a transação
inteira é abortada. Em outras palavras, uma transação é tratada
como única e indivisível unidade lógica de trabalho.

 A consistência indica a permanência do estado consistente do


banco de dados. A transação leva o banco de dados de um estado
consistente a outro. Quando é concluída, o banco deve estar em
um estado consistente. Se qualquer parte da transação violar uma
restrição de integridade, toda a transação é abortada.
55
Laboratório de Banco de Dados

 O isolamento significa que os dados utilizados durante a execução


de uma transação não podem ser utilizados por uma segunda
transação até que a primeira seja concluída. Em outras palavras, se
uma transação Tl estiver sendo executada e utilizar o item de dado X,
esse item não pode ser acessado por nenhuma outra transação (T2,
T3, T4... Tn) até que Tl termine. Essa propriedade é especialmente
útil em ambientes de bancos de dados multiusuário, pois vários
usuários podem acessar e atualizar o banco simultaneamente.

 A durabilidade garante que, uma vez feitas (consolidadas)


alterações pelas transações, elas não podem ser desfeitas ou perdidas,
mesmo em caso de falha de sistema.

 Ser serializável garante que o escalonador da execução atual


das transações produza resultados consistentes. Essa propriedade
é importante em bancos de dados distribuídos e de multiusuário,
em que várias transações provavelmente serão executadas de modo
simultâneo. Naturalmente, se apenas uma transação for executada,
a serialização não é problema.

Banco de Dados Monousuário: só possui um usuário conectado


ao mesmo tempo.
Banco de Dados Multiusuário: possui ou pode possuir vários
usuários conectados ao mesmo tempo.

Por sua natureza, o sistema de bancos de dados monousuário garante


a serialização e o isolamento do banco, pois apenas uma transação é
executada por vez. A atomicidade, consistência e durabilidade de
transações devem ser garantidas pelos SGBD monousuários. (Mesmo
esse tipo de sistema deve gerenciar a recuperação de erros criados por
interrupções induzidas pelo sistema operacional, quedas de energia e
execuções inadequadas de aplicações.).

Os bancos de dados multiusuário normalmente estão sujeitos a várias


transações concorrentes. Portanto, esses sistemas devem implementar
controles para garantir a serialização e o isolamento de transações -
além de atomicidade e durabilidade - de modo a proteger a consistência
e a integridade do banco de dados. Por exemplo, se várias transações
concorrentes forem executadas sobre o mesmo conjunto de dados
e a segunda transação atualizar o banco de dados antes do término
da primeira, a propriedade de isolamento será violada e o banco de
dados não será mais consistente. O SGBD deve gerenciar as transações
utilizando técnicas de controle de concorrência para evitar essas
56
Prof. Eros Estevão de Moura

situações indesejáveis (veremos estas técnicas neste mesmo capítulo,


mais à frente).

O Instituto Nacional Americano de Padrões (ANSI) definiu os padrões


que determinam as transações de bancos de dados em SQL. O suporte
a transações é fornecido por dois comandos de SQL: COMMIT e
ROLLBACK. Os padrões da ANSI exigem que, quando uma sequência
de transações é iniciada pelo usuário ou por um aplicativo, ela deve
prosseguir por todos os comandos de SQL subsequentes até ocorrer um
dos seguintes eventos:

 chegar a um comando COMMIT, caso em que todas as alterações


são registradas de maneira permanente no banco de dados. Esse
comando encerra automaticamente a transação de SQL;

 chegar com sucesso ao fim de um programa, caso em que todas


as alterações são registradas de maneira permanente no banco de
dados. Essa ação é equivalente a COMMIT;

 o programa seja encerrado de modo anormal, caso em que todas


as alterações feitas no banco de dados são abortadas e retorna a seu
estado consistente anterior. Essa ação é equivalente a ROLLBACK.

A utilização de COMMIT pode ser ilustrada em um outro exemplo:


vamos pegar como exemplo simples uma venda, que atualiza a
quantidade disponível do produto (tabela produto) e o saldo do cliente
“112233” quando compra duas unidades do produto “1234”, ao preço de
R$ 10,00 por unidade (em um total de R$ 20,00) e debita a compra na
conta do cliente:

(Observe que o exemplo é simplificado para facilitar a demonstração


da transação. No banco de dados, a transação poderia envolver várias
atualizações adicionais de tabelas.)

Na verdade, o comando COMMIT utilizado nesse exemplo não é


necessário se o comando UPDADE for a última ação da aplicação e se
encerrar normalmente. No entanto, a boa prática de programação impõe
a inclusão desse comando no final de uma declaração de transação.
57
Laboratório de Banco de Dados

A transação começa implicitamente quando é encontrado o primeiro


comando de SQL. Nem todas as implementações dessa linguagem seguem
o padrão ANSI; algumas (como o SQL Server) utilizam comandos de
gerenciamento de transações como: BEGIN TRANSACTION; para indicar
o início de uma nova transação. Outras implementações de SQL permitem
atribuir características das transações como parâmetros do comando BEGIN.
Por exemplo, o SGBDR Oracle utiliza comando SET TRANSACTION para
declarar o início e as propriedades de uma nova transação.

Como em qualquer transação, neste exemplo, caso houvesse algum


problema no comando UPDATE 1 (atualização do produto) ou no
comando UPDATE 2 (atualização do cliente), o banco de dados voltaria
à posição anterior, ao primeiro comando, ou seja, se houver um erro, o
banco de dados voltaria ao estado anterior como se nenhum comando
tivesse sido realizado.

4.1.3 Log de Transações

O SGDB utiliza o log de transações para rastrear todas as transações que


atualizam o banco de dados. As informações armazenadas nesse log são
utilizadas pelo SGBD em uma solicitação de recuperação acionada pelo
comando ROLLBACK, pelo encerramento anormal de um programa ou
por uma falha de sistema como discrepância de rede ou falha de disco.
Alguns SGBD utilizam o log de transações para recuperar: um estado
consistente de banco de dados, refazendo operações perdidas. Por
exemplo: após uma falha no servidor, o Oracle desfaz automaticamente
as transações não consolidadas e refaz as transações consolidas (que
tiveram COMMIT), mas que ainda não haviam sido gravadas no banco
de dados físico. Esse comportamento é necessário para a correção das
transações e é comum em qualquer SGBD transacional.

No SGBD Oracle existe uma área da memória chamada de Redo


Log Buffer. Esta área é utilizada pra minimizar o acesso a disco. O
banco primeiro grava em memória a transação para depois gravar
em disco. Isto é assim, porém o usuário só recebe a confirmação
de sua transação quando estes dados que estão na memória forem
gravados em disco.
Os arquivos de logs, chamados no Oracle de Redo Log Files, são
importantíssimos para a integridade do banco de dados, tanto é que
no Oracle é possível escolher mais de um local para gravar os Redo
Log Files, e, embora isso possa comprometer a performance, em
alguns casos vale a pena.
58
Prof. Eros Estevão de Moura

Enquanto o SGBD executa transações que modificam o banco


de dados, também atualiza automaticamente o log de transações.
Esse log armazena:

 Um registro do início da transação.

 Para cada componente de transação (comando de SQL),:

• tipo de operação sendo executada (atualização, exclusão,


inserção);

• nomes dos objetos afetados pela transação (nome da tabela);

• valores de “antes” e “depois” nos campos sendo atualizados;

• ponteiros para as entradas anteriores e posteriores da


mesma transação no log.

 O fim (COMMIT) da transação (quando houver).

Embora a utilização de log de transações aumente a carga de


processamento do SGBD, a possibilidade de restaurar um banco de
dados corrompido faz com que valha a pena.

A Tabela 1 ilustra um log de transações simplificado que reflete uma


transação básica composta de dois comandos UPDATE de SQL. Se
ocorrer uma falha de sistema, o SGBD examinará todas as transações
não consolidadas ou incompletas nesse log e restaurará (ROLLBACK)
o banco de dados a seu estado anterior com base nessas informações.
Concluído o processo de recuperação, o SGBD gravará no log todas as
transações consolidadas que não tenham sido gravadas fisicamente no
banco antes da ocorrência da falha.

Tabela 1 Log de transações (Rob e Coronel, 2011)


TRL_ TRX_ PTR PTR VALOR VALOR
OPERAÇÃO TABELA ID DE LINHA ATRIBUTO
ID NUM ANTERIOR SEGUINTE ANTES DEPOIS
341 101 Nulo 352 START ***** Inicio
da Transação
352 101 341 363 UPDATE PRODUCT 1558-QW1 PROD_ 25 23
QOH
363 101 352 365 UPDATE CLIENTE 10011 CUST_ 525,75 615,73
BALANCE
365 101 363 Nulo COMMIT **** Fim da
Transação
TRL_ID = ID de registro no log de transações PTR = Ponteiro para uma ID de registro
no log de transações
TRX_NUM = Numero de transação
(Observação: O número de transação é atribuido
automaticamente pelo SGBD.)

Se for emitido um comando ROLLBACK antes do encerramento de uma


transação, o SGBD restaurará o banco de dados apenas para essa transação
59
Laboratório de Banco de Dados

específica, não para todas, mantendo a durabilidade das transações


anteriores. Em outras palavras, as transações consolidadas não são desfeitas.

O log de transações é parte fundamental do banco de dados e


normalmente é implementado como um ou mais arquivos gerenciados
separadamente dos arquivos reais do banco. Esse log está sujeito a
riscos comuns, como situações de disco cheio ou de falha de disco.
Como ele contém alguns dos dados mais importantes de um SGBD,
certas implementações dão suporte a logs em vários discos diferentes,
reduzindo as consequências de falha de sistema.

No Oracle, estas transações vão sendo inseridas nos Rollback


Segments.

4.2 Controle de Concorrência

Segundo (Date, 2003), o termo concorrência se refere ao fato de que


os SGBD, em geral, permitem que muitas transações tenham acesso ao
mesmo banco de dados ao mesmo tempo. Em um sistema desse tipo,
é necessário algum tipo de mecanismo de controle para assegurar que
transações concorrentes não interfiram umas com as outras.

A coordenação da execução simultânea de transações em um


sistema de banco de dados multiusuário é conhecida como controle
de concorrência. O objetivo desse controle é garantir a serialização
das transações nesse tipo de ambiente. O controle de concorrência
é importante porque a execução simultânea de transações em
um banco de dados compartilhado pode dar origens a diversos
problemas de integridade e consistência de dados. Os três principais
problemas são as atualizações perdidas, os dados não consolidados e
as recuperações inconsistentes.

4.2.1 Atualizações Perdidas

O problema das atualizações perdidas ocorre quando duas transações


concorrentes, Tl e T2, estão atualizando o mesmo elemento de dados e
uma das atualizações é perdida (sobrescrita por outra aplicação). Para
ver um exemplo de atualizações perdidas, examinemos uma tabela
simples de produtos (PRODUTO). Um dos atributos dessa tabela é a
quantidade disponível (Q_PRODUTO). Suponha que haja um produto
cujo valor atual de Q_PRODUTO seja 50. Suponha também que
existam duas transações concorrentes, T1 e T2, que atualiza o valor de
Q_PRODUTO para o mesmo item da tabela PRODUTO. As transações
são apresentadas na Tabela 2.
60
Prof. Eros Estevão de Moura

Tabela 2 Transações concorrentes

Transação Computação
T1: compras 80 Q_PRODUTO= Q_PRODUTO + 80
T2: vendas Q_PRODUTO= Q_PRODUTO - 20

A Tabela 3 mostra a execução em série dessas transações em circuns-


tâncias normais, produzindo o resultado correto Q_PRODUTO = 110.

Tabela 3 Execução em série das duas transações

Tempo Transação Etapa Valor Armazenado


1 T1 Leitura de Q_PRODUTO 50
2 T1 Q_PRODUTO = 50 + 80
3 T1 Gravação de Q_PRODUTO 130
4 T2 Leitura de Q_PRODUTO 130
5 T2 Q_PRODUTO = 130 - 20
6 T2 Gravação de Q_PRODUTO 110

Suponha, no entanto, que uma transação seja capaz de ler o valor de


Q_PRODUTO de um produto tabela antes da transação anterior (que
utiliza o mesmo produto) ser consolidada. A sequência representada na
Tabela 4 mostra como pode surgir o problema de atualizações perdidas.
Observe que a primeira transação (Tl) ainda não foi consolidada quando
da execução da segunda (T2). Portanto, T2 ainda opera o valor de 50 e
o resultado de sua subtração na memória é 30. Enquanto isso, Tl grava
o valor 130 no disco é imediatamente sobrescrito por T2. Em suma, a
adição de 80 unidades é “perdida” durante o processo.

Tabela 4 Atualizações perdidas

Tempo Transação Etapa Valor Armazenado


1 T1 Leitura de Q_PRODUTO 50
2 T2 Leitura de Q_PRODUTO 50
3 T1 Q_PRODUTO = 50 + 80
4 T2 Q_PRODUTO = 50 - 20
5 T1 Gravação de Q_PRODUTO (será perdida) 130
6 T2 Gravação de Q_PRODUTO 30

4.2.2 Dados não Consolidados

O fenômeno de dados não consolidados (não salvos) ocorre quando


duas transações, T1 e T2, são executadas de modo concorrente e a
primeira (T1) é desfeita após a segunda (T2) ter acessado os dados
não consolidados, violando, assim, a propriedade do isolamento de
transações. Para ilustrar essa possibilidade, utilizaremos a mesma
transação descrita durante a discussão sobre atualizações perdidas.
T1 possui duas partes indivisíveis, uma das quais é a atualização do
61
Laboratório de Banco de Dados

estoque (Q_PRODUTO em PRODUTO), sendo a outra, possivelmente,


a atualização do total de fatura (não considerada). É necessário desfazer
T1 em função de um erro durante a atualização do total de fatura.
Assim, é totalmente abortada, desfazendo também a atualização de
estoque. Nesse caso, a transação T1 é desfeita eliminando-se a adição de
80 unidades (Tabela 5). Como T2 subtrai 20 das 50 unidades originais,
a resposta correta deve ser 30.

Tabela 5 Transações que criam o problema de dados não consolidados

Transação Etapa
T1 Q_PRODUTO = 50 + 80 (desfeita)
T2 Q_PRODUTO = 50 - 20

A Tabela 6 mostra como, nas circunstâncias normais, a execução em


série dessas transações produz o resultado correto.

Tabela 6 Circunstâncias normais, a execução em série

Tempo Transação Etapa Valor Armazenado


1 T1 Leitura de Q_PRODUTO 50
2 T1 Q_PRODUTO = 50 + 80
3 T1 Gravação de Q_PRODUTO 130
4 T1 ROLLBACK 50
5 T2 Leitura de Q_PRODUTO 50
6 T2 Q_PRODUTO = 50 - 20
7 T2 Gravação de Q_PRODUTO 30

4.2.3 Recuperações Inconsistentes

As recuperações inconsistentes ocorrem quando uma transação acessa


dados antes e após outras transações terminarem de trabalhar com esses
dados. Por exemplo, esse problema ocorreria se a transação T1 calcular
uma função de sumarização (agregada) de um conjunto de dados,
enquanto outra transação (T2) estiver atualizando os mesmos dados. O
problema é que a transação pode ler alguns dados antes de serem alterados
e outros após a alteração, produzindo, assim, resultados inconsistentes.
Para ilustrar esse problema, suponha as seguintes condições:

1- T1 calcula a quantidade total (função de agregação SUM) disponível


dos produtos armazenados na tabela PRODUTO.

2- Ao mesmo tempo, T2 atualiza a quantidade disponível (UPDATE


PRODUTO na coluna Q_PRODUTO) de dois produtos dessa
mesma tabela.

As duas transações são apresentadas na Tabela 6.


62
Prof. Eros Estevão de Moura

Tabela 7 Recuperação durante atualização

Transação T1 Transação T2
UPDATE produto
SELECT SUM(q_produto)
SET q_produto = q_produto + 100
FROM produto;
WHERE cod_produto = ‘1234’;
UPDATE produto

SET q_produto = q_produto - 100

WHERE cod_produto = ‘1235’;


COMMIT;

Enquanto T1 calcula a quantidade total disponível (Q_PRODUTO)


de todos os itens, T2 representa correção de um erro de digitação: o
usuário adiciona 100 unidades a Q_PRODUTO do produto 1234, mas
queria adicionar 100 unidades ao mesmo atributo do produto 1235.
Para corrigir o problema, usuário soma 100 a Q_PRODUTO do produto
5678 e subtrai 100 desse atributo do produto 1234.

Embora os resultados finais apresentados na Tabela 6 estejam corretos


após o ajuste, a Tabela 7 demonstra que são possíveis recuperações
inconsistentes durante a execução de transações, tornando incorreto o
resultado de T1 (o SELECT SUM).

É óbvio que a resposta calculada 405 está errada, pois sabemos que
a resposta correta é 305. A menos que o SGBD aplique o controle de
concorrência, um ambiente de banco de dados de multiusuário pode
criar catástrofes no sistema de informação.

Tabela 8 Recuperações inconsistentes

TEMPO TRANSAÇÃO AÇÃO VALOR TOTAL


1 T1 Leitura de Q_PRODUTO para COD_PRODUTO = '1111' 8 8
2 T1 Leitura de Q_PRODUTO para COD_PRODUTO = '2222' 32 8+32=40
3 T2 Leitura de PROD_QOH para COD_PRODUTO = '1234' 15
4 T2 Q_PRODUTO = 15 + 100
5 T2 Gravação de Q_PRODUTO para COD_PRODUTO = '1234' 115
6 T1 Leitura de Q_PRODUTO para COD_PRODUTO = '1234' 115 (Depois) 40+115=155
7 T1 Leitura de Q_PRODUTO para COD_PRODUTO = '5678' 230 (Depois) 155+230=285
8 T2 Leitura de Q_PRODUTO para COD_PRODUTO = '5678' 230
9 T2 Q_PRODUTO = 230-100
10 T2 Gravação de Q_PRODUTO para COD_PRODUTO = '5678' 130
11 T2 ***** COMMIT *****
12 T1 Leitura de Q_PRODUTO para PROD_CODE = '3333' 10 (Depois) 285+10=385
13 T1 Leitura de Q_PRODUTO para COD_PRODUTO = '4444' 20 (Depois) 285+20=405
63
Laboratório de Banco de Dados

No Oracle, quando você envia uma consulta ao SGBD ele não


pegará nenhuma alteração feita após o instante da sua solicitação.
Mesmo que haja um comando UPDATE, INSERT ou DELETE
executados e confirmados após a sua a solicitação, ele não levará
em conta. O Oracle tira uma “foto” do banco no momento que você
envia a solicitação. Nesta foto, só constarão os dados do instante
em que você enviou a solicitação. Ele faz isso tentando utilizar uma
área da memória chamada Redo Log Buffer. Quando o Redo Log
Buffer foi sobrescrito por novos dados de novas transações, passa a
ser impossível que ele retorne a consulta com a “foto” que foi tirada
no momento da solicitação da consulta. Neste caso, você recebe uma
mensagem de erro “snapshot too old”, alguma coisa como sua foto
está muito velha. Este é mais um motivo para não se rodar relatórios
pesados em momento de muito uso do SGBD.

4.2.4 Escalonador

Agora você sabe que podem aparecer problemas graves quando são
executadas duas ou mais transações concorrentes. Sabe, também, que
uma transação de bancos de dados envolve uma série de operações de
E/S que levam o banco de um estado consistente a outro. Finalmente,
sabe que se pode garantir a consistência do banco de dados apenas antes e
depois da execução de transações. Um banco de dados sempre passa por
um temporário e inevitável estado de inconsistência durante a execução
de uma transação se ela atualizar várias tabelas/registros. (Se a transação
contiver apenas uma atualização, não haverá inconsistência temporária.)
Essa inconsistência ocorre porque o computador executa as operações
em série, uma após a outra. Durante esse processo, a propriedade
de isolamento evita que as transações acessem os dados ainda não
liberados por outras transações. O trabalho do escalonador é ainda mais
importante nos dias de hoje, com a utilização de processadores de vários
núcleos que possuem a capacidade de executar diversas instruções ao
mesmo tempo. O que aconteceria se duas transações fossem executadas
de modo concorrente e acessas os mesmos dados?

Nos exemplos anteriores, as operações dentro de uma transação eram


executadas em ordem arbitrária. Contanto que duas transações, Tl e T2,
acessem dados não relacionados, não há conflito e a ordem da execução
é irrelevante para o resultado final. Mas se as transações operarem
sobre dados relacionados (ou os mesmos dados), há a possibilidade de
conflito entre seus componentes e a seleção de determinada ordem de
execução pode ter consequências indesejáveis. Sendo assim, como se
pode determinar a ordem correta e quem faz isso? Felizmente, o SGBD
trata dessa atribuição traiçoeira utilizando um escalonador embutido.
64
Prof. Eros Estevão de Moura

Um escalonador é um processo especial do SGBD que estabelece a


ordem em que são executadas operações de transações concorrentes.
O escalonador intercala a execução de operações de banco de dados,
garantindo a serialização e o isolamento das transações. Para determinar
a ordem adequada, escalonador baseia suas ações em algoritmos de
controle de concorrência, como os métodos de bloqueio ou time stamping,
explicados nas próximas seções. No entanto, é importante compreender
que nem todas as transações são serializáveis. O SGBD determina
quais transações são serializáveis e procede intercalando a execução de
suas operações. Em geral, as transações que não são serializáveis são
executadas pelo SGBD por ordem de chegada. O principal trabalho do
escalonador é criar uma escala serializável de operações de transação.
Uma escala serializável é uma escala de operações transacionais na qual
a execução intercalada das transações (Tl, T2, T3 etc.) produz o mesmo
resultado, como se as transações fossem executadas em ordem serial
(uma após a outra).

Segundo (Rob e Coronel, 2011), o escalonador também assegura


que a unidade central de processamento (CPU) e os sistemas de
armazenamento do computador sejam utilizados de modo eficiente.
Se não houvesse um modo de escalonar a execução de transações,
todas seriam executadas por ordem de chegada. O problema com essa
abordagem é que se desperdiçaria tempo de processamento, pois a CPU
teria de esperar que as operações de WRITE terminassem, perdendo
vários ciclos de processamento. Em suma, o escalonamento por ordem
de chegada tende a resultar em tempos de resposta inaceitáveis no
ambiente de SGBD de multiusuário. Portanto, é necessário outro método
de escalonamento para aprimorar a eficiência do sistema em geral.

Além disso, o escalonador facilita o isolamento de dados, garantindo


que duas transações não atualizem o mesmo elemento simultaneamente.
As operações de bancos de dados podem exigir ações de leitura e/ou
gravação que causem conflitos. Por exemplo, a Tabela 8 mostra possíveis
cenários de conflito em que duas transações, Tl e T2, são executadas de
modo concorrente sobre os mesmos dados. Observe que nessa tabela
duas operações entram em conflito quando acessam os mesmos dados
e pelo menos uma delas utilize uma operação de gravação (WRITE).
65
Laboratório de Banco de Dados

Tabela 9 Cenários de conflito de leitura/gravação: matriz de operações conflitantes de


banco de dados (Rob e Coronel, 2011)

TRANSAÇÕES
T1 T2 Resultado
Operações Leitura Leitura Sem conflito
Leitura Gravação Conflito
Gravação Leitura Conflito
Gravação Gravação Conflito

Foram propostos vários métodos para escalonar a execução de


operações conflitantes de transações concorrentes. Esses métodos foram
classificados como bloqueio, time stamping e otimista. Os métodos de
bloqueio, discutidos a seguir, são utilizados com mais frequência.

Controle de Concorrência com Métodos de Bloqueio

O bloqueio garante a utilização exclusiva de um item de dados por uma


transação atual. Em outras palavras, a transação T2 não tem acesso a
um item de dados que esteja atualmente sendo utilizado pela transação
T1. As transações adquirem um bloqueio antes de acessar os dados. O
bloqueio é liberado (desbloqueado) quando a transação é concluída, de
modo que outra transação possa bloquear o item de dados para seu uso
exclusivo.

Lembre-se de que, baseado nas propriedades das transações, que a


consistência de dados não pode ser garantida durante uma transação
(inconsistência temporária, ler 4.2.4). O banco pode estar em um estado
inconsistente temporário quando muitas transações são executadas.
Portanto, os bloqueios são necessários para evitar que outras transações
leiam dados inconsistentes.

A maioria dos SGBD multiusuário inicia e aplica automaticamente


os procedimentos de bloqueio. Todas as informações bloqueadas
são gerenciadas pelo gerente de bloqueio, responsável por atribuir e
inspecionar os bloqueios utilizados pelas transações.

Granularidade de Bloqueio

A granularidade de bloqueio indica o nível de utilização de bloqueio.


Ele pode ocorrer nos seguintes níveis: banco de dados, tabela, página,
linha e campo (atributo).
66
Prof. Eros Estevão de Moura

Nível de banco de dados

Em um bloqueio no nível de banco de dados, o banco inteiro é


bloqueado, evitando, assim, a utilização de qualquer uma de suas tabelas
pela transação T2 enquanto a transação T1 estiver sendo executada.
Esse nível de bloqueio é bom para processos de batch, mas inadequado
para SGBD multiusuário. Imagine quão lento seria o acesso a dados se
milhares de transações tivessem de esperar a conclusão da transação
anterior antes de poderem reservar o banco de dados inteiro! A Figura
1 ilustra o bloqueio no nível de banco de dados. Observe que, em razão
desse bloqueio, as transações T1 e T2 não podem acessar o mesmo
banco de dados simultaneamente, ainda que utilizem tabelas diferentes.

Figura 1 Sequência de bloqueio no nível de banco de dados (Rob e Coronel, 2011)

Tempo Banco de dados de folha de pagamento


Transação 1 (T1) Transação 2 (T2)
(Atualiza a tabela A) (Atualiza a tabela B)
Tabela A
1 Solicitação de bloqueio Solicitação de bloqueio
de banco de dados de banco de dados

2 Bloqueado OK Aguardar

5 Tabela A
OK Bloqueado
6 Desbloqueado

9
Desbloqueado

Nível de tabela

Em um bloqueio no nível de tabela, a tabela inteira é bloqueada,


impedindo que a transação T2 acesse qualquer linha enquanto a
transação T1 estiver utilizando a tabela. Se uma transação solicitar
acesso a várias tabelas, todas podem ser bloqueadas. No entanto, duas
transações podem acessar o mesmo banco de dados contanto que
acessem tabelas diferentes.

Os bloqueios no nível de tabela, embora menos restritivos do que os


no nível de banco de dados, provocam congestionamentos quando
muitas transações esperam para acessar a mesma tabela. Essa
situação é especialmente desagradável se o bloqueio forçar um atraso
quando transações diferentes solicitarem acesso a partes diferentes
da mesma tabela, caso em que as transações não interfeririam entre
67
Laboratório de Banco de Dados

si. Consequentemente, os bloqueios nesse nível não são adequados a


SGBD multiusuário. A Figura 2 ilustra o efeito de um bloqueio no nível
de tabela. Observe que, nessa figura, as transações T1 e T2 não podem
acessar a mesma tabela, mesmo se tentarem utilizar linhas diferentes:
T2 tem de esperar até T1 desbloqueie a tabela.

Figura 2 Sequência de bloqueio no nível de tabela (Rob e Coronel, 2011)

Tempo Banco de dados de folha de pagamento

Transação 1 (T1) Transação 2 (T2)


(Atualiza a linha 5) Tabela A (Atualiza a linha 30)

Solicitação de bloqueio Solicitação de bloqueio


2
da Tabela A da Tabela A
Bloqueado OK AGUARDAR
3

Tabela A OK Bloqueado
5

Desbloqueado
7 (fim da transação 1) Desbloqueado
(fim da transação 2)

Nível de página

Em um bloqueio no nível de página, o SGBD bloqueia uma página


de disco inteira. A página de disco, ou simplesmente página, é o
equivalente a um bloco de discos, que pode ser descrito como uma
seção diretamente endereçável de um disco. Uma página tem tamanho
fixo, como 4K, 8K ou 16K. Por exemplo, caso deseje gravar apenas 73
bytes em uma página de 4K, essa página inteira tem de ser lida do disco,
atualizada na memória e gravada de volta no disco. Uma tabela pode
usar várias páginas e uma página pode conter várias linhas de uma ou
mais tabelas. Segundo (Rob e Coronel, 2011), os bloqueios no nível de
página são atualmente o método mais utilizado em SGBD multiusuário.
Um exemplo desse tipo de bloqueio é apresentado na Figura 3. Observe
que T1 e T2 acessam a mesma tabela, enquanto bloqueiam páginas de
disco diferentes. Se T2 solicitar a utilização de uma linha localizada em
uma página bloqueada por T1, T2 deve esperar até que a página seja
desbloqueada por T1.
68
Prof. Eros Estevão de Moura

Figura 3 - Sequência de bloqueio no nível de página (Rob e Coronel, 2011)

Banco de dados de
Tempo Transação 1 (T1)
folha de pagamento
Transação 2 (T2)
(Atualiza a linha 1) (Atualiza as linhas 5 e 2)
Tabela A
Solicitação de bloqueio
da página 1 1
1 Solicitação de bloqueio
Bloqueado OK 2 Página 1 da página 2
2
3 OK Bloqueado
3 Solicitação de bloqueio
4
da página 1
4 5 Página 2 Aguardar

5 6
OK Bloqueado
6
Desbloqueio da página 1 e 2
Desbloqueio da (fim da transação)
7
página 1
(fim da transação) Número da linha

Nível de linha

O bloqueio no nível de linha é muito menos restritivo do que


os discutidos anteriormente. O SGBG permite que transações
concorrentes acessem linhas diferentes da mesma tabela, mesmo
quando estas estiverem localizadas na mesma página. Embora esse tipo
de abordagem de bloqueio aumente a disponibilidade de dados, seu
gerenciamento exige alta carga de processamento, pois há um bloqueio
para cada linha de uma tabela do banco de dados envolvida em uma
transação conflitante. Os SGBD modernos passam automaticamente
o bloqueio do nível de linha para o nível de página quando a seção
de aplicação solicita vários bloqueios na mesma página. A Figura 4
ilustra a utilização de um bloqueio a nível de linha. Observe na Figura
4 que ambas as transações podem ser executadas simultaneamente,
mesmo se as linhas solicitadas estiverem na mesma página. T2 tem de
esperar se solicitar a mesma linha de T1.

Figura 4 Sequência de bloqueio no nível de linha (Rob e Coronel, 2011)

Banco de dados de
Tempo Transação 1 (T1)
folha de pagamento
Transação 2 (T2)
(Atualiza a linha 1) (Atualiza a linha 2)
Tabela A
Solicitação de bloqueio
da linha 1 1
1
Solicitação de bloqueio
2 Página 1 da linha 2
2
Bloqueado OK 3
OK Bloqueado
3
4
4 5 Página 2
5 6
Desbloqueio
6 da linha 2
(fim da transação)

Número da linha
69
Laboratório de Banco de Dados

Nível de campo

O bloqueio no nível de campo permite que transações concorrentes


acessem a mesma linha, contanto que solicitem a utilização de
campos (atributos) diferentes nessa linha. Embora esse tipo de
bloqueio resulte claramente no acesso mais flexível de dados de
multiusuário, raramente é implementado no SGBD, pois exige um
nível extremamente alto de carga do computador e, na prática, o
bloqueio no nível de linha é muito mais útil.

Tipos de Bloqueio

Independente do nível de bloqueio, o SGBD pode utilizar diferentes


tipos: binário ou compartilhado/exclusivo.

Bloqueios binários

O bloqueio binário possui apenas dois estados: bloqueado (1) e


desbloqueado (0). Se um objeto - ou seja, um banco de dados, tabela,
página ou linha - for bloqueado por uma transação, nenhuma outra
pode utilizá-lo. Se um objeto estiver desbloqueado, qualquer transação
pode bloqueá-lo para seu uso. Toda operação de banco de dados exige
que o objeto afetado esteja bloqueado. Como regra, uma transação
deve desbloquear o objeto após seu encerramento. Portanto, todas
as transações solicitam uma operação de bloqueio e desbloqueio
para cada item de dados acessado. Essas operações são gerenciadas
e escalonadas automaticamente pelo SGBD. O usuário não precisa se
preocupar sobre o bloqueio e desbloqueio de itens de dados. (Todo
SGBD possui um mecanismo-padrão de bloqueio. Se o usuário final
quiser substituir o padrão, existe, entre outros comandos de SQL, o
LOCK TABLE, que realiza essa tarefa.).

A técnica de bloqueio binário é ilustrada na Tabela 9, que utiliza o


problema de atualizações perdidas da Tabela 4. Observe que os recursos
de bloqueio e desbloqueio eliminam o problema de atualizações perdidas,
pois o item não é liberado até que o comando de gravação (WRITE) esteja
concluído. Portanto, o valor de Q_PRODUTO não pode ser utilizado
até que tenha sido adequadamente atualizado. No entanto, os bloqueios
binários são considerados atualmente muito restritivos para produzir
condições ideais de concorrência. Por exemplo, o SGBD não permitirá
que duas transações leiam o mesmo objeto de banco de dados, mesmo que
nenhuma delas atualize o banco e, portanto, não possa ocorrer nenhum
problema de concorrência. Lembre-se da Tabela 8, em que os conflitos
de concorrência ocorrem apenas quando duas transações são executadas
simultaneamente e uma delas atualiza o banco.
70
Prof. Eros Estevão de Moura

Tabela 10 Exemplo de bloqueio binário

TEMPO TRANSAÇÃO ETAPA VALOR ARMAZENADO


1 T1 Bloqueio de PRODUTO
2 T1 Leitura de Q_PRODUTO 50
3 T1 Q_PRODUTO = 50 + 80
4 T1 Gravação de Q_PRODUTO 130
5 T1 Desbloqueio de PRODUTO
6 T2 Bloqueio de PRODUTO
7 T2 Leitura de Q_PRODUTO 130
8 T2 Q_PRODUTO = 130 - 20
9 T2 Gravação de Q_PRODUTO 110
10 T2 Desbloqueio de PRODUTO

Bloqueios compartilhados/exclusivos

As identificações “compartilhado” e “exclusivo” indicam a natureza


do bloqueio. O bloqueio exclusivo ocorre quando o acesso é
reservado especificamente para a transação que bloqueou o objeto.
Ele deve ser utilizado quando houver potencial para conflitos. (veja
a Tabela 8). O bloqueio compartilhado ocorre quando transações
concorrentes recebem acesso de leitura com base em um bloqueio
comum. Ele não produz conflitos, contanto que todas as transações
sejam apenas para leitura.

O bloqueio compartilhado é emitido quando uma transação deseja ler


dados a partir de um banco, sem que outra transação tenha bloqueio
exclusivo sobre esses dados. O bloqueio exclusivo é emitido quando
uma transação deseja atualizar (gravar) um item de dados sem que
haja qualquer bloqueio atual de outra transação nesse item. Utilizando
o conceito de compartilhamento/exclusividade, um bloqueio pode
apresentar três estados: desbloqueado, compartilhado (leitura) e
exclusivo (gravação).

Conforme apresentado na Tabela 8, duas transações entram em conflito


somente quando pelo menos uma delas for de gravação (WRITE). Como
é possível executar duas transações de leitura (READ) com segurança, os
bloqueios compartilhados permitem que várias dessas transações leiam
o mesmo item de dados simultaneamente. Por exemplo, se a transação
T1 possuir um bloqueio compartilhado sobre o item de dados X e a
T2 quiser ler esse mesmo item, ela também pode obter um bloqueio
compartilhado sobre ele.
71
Laboratório de Banco de Dados

Para a transação T2 atualizar o item X, ela solicita um bloqueio exclusivo


sobre tal item. O bloqueie exclusivo é concedido se e somente se nenhum
outro bloqueio for mantido sobre o item de dados.

Portanto, se a transação T1 já tiver um bloqueio compartilhado ou


exclusivo sobre o item X, não será possível conceder um bloqueio
exclusivo para a transação T2 e ela deverá aguardar até a consolidação
(COMMIT) de T1. Essa condição é conhecida como regra da
exclusividade mútua: apenas uma transação por vez pode possuir
bloqueio exclusivo sobre o mesmo objeto.

Embora a utilização de bloqueios compartilhados torne mais eficiente o


acesso aos dados, esse tipo de esquema aumenta a carga do gerente de
bloqueio por vários motivos:

 o tipo de bloqueio mantido deve ser conhecido antes que um


bloqueio possa ser concedido;

 há três operações de bloqueio: READ_LOCK (para verificar


o tipo de bloqueio), WRITE_LOG (para emitir o bloqueio) e
UNLOCK (para liberar o bloqueio);

 o esquema foi aprimorado para permitir a atualização para um


nível superior (de compartilhado para exclusivo) e inferior (de
exclusivo para compartilhado) de bloqueio.

Embora os bloqueios evitem inconsistências de dados graves, podem


levar a dois problemas importantes:

 a escala de transações resultante pode não ser serializável;

 a escala pode criar deadlocks. O deadlock de bancos de dados,


equivalente ao tráfego caótico de uma grande cidade, ocorre quando
duas ou mais transações aguardam a liberação dos dados pela outra.
T1 aguarda T2 e T2 aguarda T1.

Felizmente, ambos os problemas podem ser gerenciados: a serialização


é garantida por meio de um protocolo de bloqueio conhecido como
bloqueio de duas fases (two-phase commit) e os deadlocks podem ser
gerenciados utilizando técnicas de detecção e prevenção. Essas técnicas
serão examinadas nas duas seções seguintes.

a) Bloqueio de duas Fases para Assegurar a Serialização (two-phase


commit)
72
Prof. Eros Estevão de Moura

O bloqueio de duas fases (two-phase commit) define como as transações


obtêm e liberam bloqueios. Ele garante a serialização, mas não evita
deadlocks. As duas fases são:

1. Fase de crescimento, em que uma transação adquire todos os


bloqueios solicitados sem desbloquear nenhum dado. Adquiridos todos
os bloqueios, a transação está no ponto bloqueado.

2. Fase de redução, em que uma transação libera todos os bloqueios e não


pode obter novos. O protocolo de bloqueio de duas fases é determinado
pelas seguintes regras:

 duas transações não podem apresentar bloqueios conflitantes;

 nenhuma operação de desbloqueio pode preceder uma operação


de bloqueio na mesma transação;

 nenhum dado é afetado até que todos os bloqueios sejam obtidos


- ou seja, até que a transação esteja em seu ponto bloqueado.

A Figura 5 ilustra o protocolo de bloqueio de duas fases.

Figura 5 Protocolo de bloqueio de duas fases (two-phase commit) (Rob e Coronel, 2011)

Ponto
bloqueado
Adquirir Liberar
bloqueio bloqueio
Adquirir Liberar
bloqueio bloqueio

Tempo 1 2 3 4 5 6 7 8

Início Operações fim

Fase de
Fase de crescimento bloqueio Fase de redução

Nesse exemplo, a transação adquire todos os bloqueios necessários


até atingir o ponto bloqueado. (No caso, a transação solicita dois
bloqueios.) Atingido esse ponto, os dados são modificados conforme as
necessidades da transação. Por fim, a transação é concluída, liberando
todos os bloqueios adquiridos na primeira fase.
73
Laboratório de Banco de Dados

O bloqueio de duas fases aumenta o custo de processamento de


transações e pode provocar outros efeitos indesejáveis. Um deles é a
possibilidade de criação de deadlocks.

b) Deadlocks

Um deadlock ocorre quando duas transações aguardam indefinidamente


que a outra desbloqueie dados. Por exemplo, se houver duas transações,
T1 e T2, do seguinte modo, ocorrerá um deadlock:

T1 = acessa os itens de dados X e Y

T2 = acessa os itens de dados Y e X

Se T1 não tiver desbloqueado o item de dados Y, T2 não poderá iniciar. Se


T2 não tiver desbloqueado o item de dados X, T1 não poderá continuar.
Consequentemente, T1 e T2 esperam que a outra desbloqueie o item de
dados solicitado. A Tabela 11 mostra como se cria uma condição de deadlock.

Tabela 11 Criação de uma condição de deadlock (Rob e Coronel, 2011)

TEMPO TRANSAÇÃO RESPOSTA STATUS DE BLOQUEIO


0 Dado X Dado Y
1 T1:LOCK(X) OK Desbloqueado Desbloqueado
2 T2:LOCK(Y) OK Bloqueado Desbloqueado
3 T1:LOCK(Y) Aguadar Bloqueado Bloqueado
4 T2:LOCK(X) Aguadar Bloqueado Bloqueado
5 T1:LOCK(Y) Aguadar Bloqueado Bloqueado
6 T2:LOCK(X) Aguadar Bloqueado Bloqueado
7 T1:LOCK(Y) Aguadar Bloqueado Bloqueado
8 T2:LOCK(X) Aguadar Bloqueado Bloqueado
9 T1:LOCK(Y) Aguadar Bloqueado Bloqueado
... ............. ............. ............. .............
... ............. ............. ............. .............
... ............. ............. ............. .............

O exemplo precedente utilizava apenas duas transações concorrentes


para mostrar uma condição de deadlock. Em um SGBD real, podem-
-se executar muito mais transações simultaneamente, o que aumenta-
rá, assim, a probabilidade de geração de deadlocks. Observe que eles
são possíveis apenas quando uma das transações obtiver um bloqueio
exclusivo sobre o item de dados. Não pode haver situação de deadlock
entre bloqueios compartilhados.
74
Prof. Eros Estevão de Moura

As três técnicas básicas de controle são:

 Prevenção de deadlocks. Uma transação que solicite novo blo-


queio é abortada se houver a possibilidade de ocorrer um deadlock.
Se a transação for abortada, todas as alterações feitas por ela serão
desfeitas e todos os bloqueios obtidos serão liberados. Em seguida, a
transação recebe novo escalonamento de execução. A prevenção de
deadlocks funciona, pois evita condições que levem a eles.

 Detecção de deadlocks. O SGBD testa, periodicamente, o banco


de dados em busca de deadlocks. Se for encontrado, uma das transa-
ções (a “vítima”) é abortada (desfeita e reiniciada) e a outra continua.

 Evasão de deadlocks. A transação deve obter todos os bloqueios


necessários antes de iniciar a execução. Essa técnica evita a necessi-
dade de desfazer transações conflitantes, exigindo que os bloqueios
sejam obtidos em sequência. No entanto, a atribuição serial de blo-
queio necessária para a evasão de deadlocks aumenta os tempos de
resposta a ações.

A escolha do melhor método de controle de deadlocks depende do


ambiente de banco de dados. Por exemplo, se a probabilidade de
deadlocks for baixa, recomenda-se a detecção. No entanto, se a pro-
babilidade for alta, a prevenção é mais adequada. Se o tempo de res-
posta não estiver entre as maiores prioridades do sistema, pode ser
empregada a evasão. Todos os SGBD atuais dão suporte à detenção
de deadlocks em bancos transacionais, ao passo que alguns utilizam
uma combinação de técnicas de prevenção e evasão em outros tipos
de dados, como os de data warehouses ou em XML.

Controle de Concorrência com Métodos de Timestamp

A abordagem de timestamp para escalonar transações correntes atribui


um registro global e exclusivo a cada transação. Esse valor produz
uma ordem explícita em que as transações são enviadas ao SGBD. O
método timestamp deve apresentar duas propriedades: exclusividade e
monotonicidade:

a exclusividade garante que não existam valores iguais do registro;


 

a monotonicidade assegura que os valores sejam sempre maiores.


 

Todas as operações de bancos de dados (leitura e gravação) dentro


da mesma transação devem ter o mesmo registro. O SGBD executa
operações conflitantes conforme a ordem do método timestamp,
garantindo, assim, a serialização das transações. Se duas transações
estiverem em conflito, uma é interrompida, desfeita, reescalonada e
recebe um novo valor de timestamp.
75
Laboratório de Banco de Dados

A desvantagem dessa abordagem é que cada valor armazenado no


banco de dados exige dois campos adicionais: um para a última vez
em que o campo foi lido e outro para a última atualização. Portanto,
o método timestamp aumenta as necessidades de memória e a carga
de processamento do banco de dados. Ele também demanda muitos
recursos do sistema, pois é possível que diversas transações tenham de
ser interrompidas, reescalonadas e recebam um novo timestamp.

Esquemas Wait/Die e Wound/Wait

Você aprendeu que os métodos de timestamp são utilizados para gerenciar


a execução de transações concorrentes. Nesta seção, você aprenderá
dois esquemas utilizados para decidir qual transação é desfeita e qual
continua sendo executada: o esquema wait/die e o esquema wound/wait.

O exemplo seguinte ilustra a diferença. Suponha que haja duas transações


conflitantes: T1 e T2, cada uma com um timestamp exclusivo. Suponha
que T1 tenha como timestamp 11000000 e T2 tenha 19000000. Pode-se
deduzir dos timestamp que T1 é a transação mais antiga (com menor
valor de timestamp) e T2 é a mais recente. Em função desse cenário, há
quatro resultados possíveis, apresentados na Tabela 12.

Tabela 12 Esquemas de controle de concorrência wait/die e wound/wait

Transação que Transação que Esquema Wait/Die Esquema Wound/Wait


Solicita Bloqueio Possui Bloqueio
T1(11000000) T2 (19000000) - T1 aguarda até que T2 - T1 tem prioridade (desfaz)
seja concluída e libere seus sobre T2.
bloqueios.
- T2 é reescalonada utilizando
o mesmo registro.
T2(19000000 T1 (11000000) - T2 é recusada (desfeita). - T2 aguarda até que T1
seja concluída e libere seus
- T2 é reescalonada bloqueios.
utilizando o mesmo
registro.

Utilizando o esquema wait/die:

a. Se a transação que solicita o bloqueio for a mais velha dentre


as duas, ela aguardará até que a outra transação seja concluída e
seus bloqueios liberados.

b. Se a transação que solicita o bloqueio for a mais nova dentre


as duas, ela será recusada (desfeita) e reescalonada utilizando o
mesmo timestamp.

Em resumo, no esquema wait/die, a transação mais antiga aguarda que


a mais nova seja concluída e libere seus bloqueios.
76
Prof. Eros Estevão de Moura

No esquema wound/wait:

a. se a transação que solicita o bloqueio for a mais velha dentre as


duas, terá precedência (prioridade sobre a transação mais nova
(desfazendo-a)). T1 tem prioridade sobre T2 quando T1 desfaz
T2. A transação mais nova, preterida, é reescalonada utilizando o
mesmo timestamp;

b. se a transação que solicita o bloqueio for a mais nova dentre as


duas, aguardará até que a outra transação seja concluída e seus
bloqueios liberados.

Resumindo, no esquema wound/wait, a transação mais antiga desfaz a


mais nova e a reescalona.

Em ambos os casos, uma das transações aguarda que a outra termine e


libere os bloqueios. No entanto em muitos casos, uma transação solicita
vários bloqueios. Por quanto tempo uma transação tem de esperar por
uma solicitação de bloqueio? Obviamente, esse cenário pode fazer com
que algumas transações aguardem indefinidamente, provocando um
deadlock. Para evitar isso, cada solicitação de bloqueio possui um valor
associado de contagem de tempo. Se o bloqueio não for concedido antes
que essa contagem termine, a transação é desfeita.

Controle de Concorrência com Métodos Otimistas

A abordagem otimista baseia-se no pressuposto de que a maioria das


operações de bancos de dados não entre em conflito. Ela não exige nem
as técnicas de bloqueio nem as de timestamp. Em vez disso, a transação
e executada sem restrições até ser consolidada (COMMIT). Em uma
abordagem otimista, cada transação passa por duas ou três fases,
chamadas: leitura, validação e gravação.

 Durante a fase de leitura, a transação lê o banco de dados, executa


as computações necessárias e faz as atualizações em uma cópia
privada dos valores do banco. Todas as operações de atualização são
registradas em um arquivo temporário, que não é acessado pelas
transações remanescentes.

 Durante a fase de validação, a transação é validada, garantindo


que as alterações feitas não afetem a integridade e a consistência do
banco de dados. Se o teste de validação for positivo, a transação passa
para a fase de gravação. Se for negativo, é reiniciada e as alterações
são descartadas.

 Durante a fase de gravação, as alterações são aplicadas


permanentemente ao banco de dados.
77
Laboratório de Banco de Dados

A abordagem otimista é aceitável na maioria dos sistemas de bancos de


dados de leitura e consulta que exigem poucas transações de atualização.

Em um ambiente densamente utilizado, o gerenciamento de deadlocks -


prevenção e detecção - constitui uma função importante do SGBD. O SGBD
utilizará uma ou mais técnicas discutidas aqui, bem como suas variações.

4.3 Resumo

Em (Rob e Coronel, 2011) é feito o seguinte resumo sobre gerenciamento


de transações e controle de concorrência:

 A transação é uma sequência de operações que acessam o


banco de dados. Ela representa um evento real. A transação deve
ser uma unidade lógica de trabalho, ou seja, nenhuma parte dela
pode existir por si mesma. Ou todas as partes são executadas ou
a transação é abortada. A transação leva o banco de dados de um
estado consistente a outro. O banco de dados em estado consistente
é aquele em que as restrições de integridade de todos os dados são
satisfeitas.

 As transações possuem quatro propriedades principais:


indivisibilidade (todas as partes são executadas; do contrário, a
transação é abortada), consistência (o estado consistente do banco
de dados é mantido), isolamento (os dados utilizados por uma
transação não podem ser acessados por outra até que a primeira
esteja concluída) e durabilidade (as alterações feitas por uma
transação não podem ser desfeitas após sua consolidação). Além
disso, os escalonamentos de transações possuem a propriedade de
serialização (o resultado da execução concorrente de transações é
igual ao da execução das transações em ordem serial).

 A SQL dá suporte a transações por meio de dois comandos:


COMMIT (salva alterações no disco) e ROLLBACK (restaura o
estado anterior do banco de dados).

 As transações de SQL são formadas por vários comandos e


solicitações aos bancos de dados. Cada solicitação origina várias
operações de E/S no banco de dados.

 O log de transações rastreia todas as transações que modificam


o banco. As informações armazenadas nesse log são utilizadas para
fins de recuperação (ROLLBACK).

 O controle de concorrência coordena a execução simultânea de


transações. A execução concorrente de transações pode resultar
78
Prof. Eros Estevão de Moura

em três problemas principais: atualizações perdidas, dados não


consolidados e recuperações inconsistentes.

 O escalonador é responsável por estabelecer a ordem em que


operações de transações concorrentes são executadas. Essa ordem é
fundamental e garante a integridade do banco de dados em sistemas
de multiusuário. O bloqueio, o timestamp e os métodos otimistas
são utilizados pelo escalonador para garantir a serialização de
transações.

 O bloqueio garante o acesso exclusivo a um item de dados por


uma transação. Ele evita que uma transação utilize um item ao
mesmo tempo de outra. Há vários níveis de bloqueio: banco de
dados, tabela, página, linha e campo.

 É possível utilizar dois tipos de bloqueios em sistemas de


bancos de dados: binários e compartilhados/exclusivos. O bloqueio
binário pode ter apenas dois estados: bloqueado (1) e desbloqueado
(0). O bloqueio compartilhado é utilizado quando uma transação
deseja ler dados a partir de um banco e nenhuma outra transação
está atualizando os mesmos dados. Pode haver vários bloqueios
compartilhados ou de “leitura” para um item específico. O bloqueio
exclusivo é emitido quando uma transação deseja atualizar (gravar)
o banco de dados e nenhum outro bloqueio (compartilhado ou
exclusivo) é mantido para os dados.

 A serialização de escalonamentos é garantida por meio da


utilização de bloqueio de duas fases. Esse esquema possui uma fase de
crescimento, em que a transação adquire todos os bloqueios necessários
sem desbloquear nenhum dado, e uma fase de encolhimento, em que
a transação libera todos os bloqueios sem adquirir novos.

 Quando duas ou mais transações aguardam indefinidamente que


a outra libere um bloqueio, elas se encontram em deadlock. Há três
técnicas de controle de deadlocks: prevenção, detecção e evasão.

 O controle de concorrência com timestamp atribui um registro


exclusivo a cada transação e escala a execução de transações
conflitantes por ordem desse registro. São utilizados dois esquemas
para decidir qual transação é desfeita e qual continua a execução: o
esquema wait/die e o esquema wound/wait.

 O controle de concorrência com métodos otimistas assume que


a maioria das transações de bancos de dados não entra em conflito
e são executadas de modo concorrente, utilizando cópias privadas
temporárias dos dados. No momento de consolidar (COMMIT),
essas cópias são atualizadas no banco.
Recuperação

Olá!
Neste capítulo, discutimos algumas das técnicas que podem ser
usadas para a recuperação do banco de dados contra falhas. No
capítulo 4, abordamos as diferentes causas de falha, como as do
sistema e erros de transação. Este capítulo apresenta conceitos
adicionais que são relevantes aos protocolos de recuperação, e
oferece uma visão geral dos diversos algoritmos de recuperação de
banco de dados.
Vamos lá!
Prof. Eros

Segundo (Silberschattz, 2006), um sistema de computador, como


qualquer outro dispositivo, está sujeito a falhas por uma série de causas:
falha de disco, falta de energia, erro de software, um incêndio na sala
e até mesmo sabotagem. Em qualquer falha, informações podem ser
perdidas. Portanto, o sistema de banco de dados precisa tomar ações
de antemão para garantir que as propriedades de atomicidade e
durabilidade das transações.

5.1 Conceitos de Recuperação

5.1.1 Esboço da recuperação e categorização dos


algoritmos de recuperação

A recuperação de falhas de transação em geral significa que o banco


de dados é restaurado ao estado consistente mais recente antes do
momento da falha. Para fazer isso, o sistema precisa manter informações
sobre as mudanças que foram aplicadas aos itens de dados pelas diversas
transações. Essa informação costuma ser mantida no log do sistema que
mantém todas as transações.

Segundo (Elmasri e Navathe, 2011), uma estratégia típica para


recuperação pode ser resumida informalmente da seguinte maneira:
80
Prof. Eros Estevão de Moura

1. se houver dano extensivo a uma grande parte do banco de dados


devido à falha catastrófica, como uma falha de disco, o método de
recuperação restaura uma cópia antiga do banco de dados que teve
backup para o arquivamento (normalmente, fita ou outro meio de
armazenamento off-line de grande capacidade) e reconstrói um
estado mais recente, reaplicando ou refazendo as operações das
transações confirmadas do log em backup, até o momento da falha.
(partindo da premissa que há um backup do banco de dados e dos
seus logs);

2. quando o banco de dados no disco não está danificado fisicamente


e uma falha não catastrófica dos tipos estudados na seção 4.2
tiver ocorrido, a estratégia de recuperação é identificar quaisquer
mudanças que possam causar uma inconsistência no banco de
dados. Por exemplo, uma transação que atualizou alguns itens do
banco de dados no disco, mas não confirmou as necessidades de ter
suas mudanças revertidas ao desfazer suas operações de gravação.
Também pode ser preciso refazer algumas operações a fim de
restaurar um estado consistente do banco de dados; por exemplo,
se uma transação tiver sido confirmada, mas algumas de suas
operações de gravação ainda não tiverem sido gravadas em disco.
Para a falha não catastrófica, o protocolo de recuperação não precisa
de uma cópia de arquivamento completa do banco de dados. Em vez
disso, as entradas mantidas no log do sistema online no disco são
analisadas para determinar as ações apropriadas para recuperação.

Conceitualmente, podemos distinguir duas técnicas principais para


recuperação de falhas de transação não catastróficas: atualização adiada
e atualização imediata.

As técnicas de atualização adiada não atualizam fisicamente o banco de


dados no disco até que uma transação atinge seu ponto de confirmação
(COMMIT); então, as atualizações são registradas no banco de dados.
Antes de atingir a confirmação, todas as atualizações de transação são
registradas no espaço de trabalho de transação local ou nos buffers da
memória principal que o SGBD mantém (o cache de memória principal
do SGBD), e isto é feito por questões de performance, pois desta forma se
acessa menos o disco. Antes da confirmação, as atualizações são gravadas
persistentemente no log (no caso do SGBD Oracle, no Redo Log File) e,
após a confirmação, elas são gravadas no banco de dados no disco. Se
uma transação falhar antes de atingir seu ponto de confirmação, ela não
terá alterado o banco de dados de forma alguma, de modo que o UNDO
não é necessário. Pode ser preciso um REDO para desfazer o efeito das
operações de uma transação confirmada com base no log, pois seu efeito
pode, ainda, não ter sido registrado no banco de dados em disco. Assim,
a atualização adiada também é conhecida como algoritmo NO-UNDO/
81
Laboratório de Banco de Dados

REDO. Não estarei entrando em detalhes sobre esta técnica; havendo


interesse, sugiro o capítulo 23 do (Elmasri e Navathe, 2011).

Nas técnicas de atualização imediata, o banco de dados pode ser atualizado


por algumas operações de uma transação antes que a transação alcance
seu ponto de confirmação. Porém, essas operações também precisam
ser registradas no log no disco ao forçar a gravação antes que elas sejam
aplicadas ao banco de dados no disco, tornando a recuperação ainda
possível. Se uma transação falhar depois de gravar algumas mudanças
no disco, mas antes de atingir seu ponto de confirmação, o efeito de suas
operações no banco de dados precisa ser desfeito; ou seja, a transação
deve ser revertida. No caso geral da atualização imediata, tanto undo
quanto redo podem ser exigidos durante a recuperação. Essa técnica,
conhecida como algoritmo UNDO/REDO, requer as duas operações
durante a recuperação, e é usada na prática. Uma variação do algoritmo,
em que todas as atualizações precisam ser registradas no banco de
dados em disco antes que a transação confirme, requer apenas undo, de
modo que é conhecida como algoritmo UNDO/NO-REDO. Não estarei
entrando em detalhes sobre esta técnica; havendo interesse, sugiro o
capítulo 23 do (Elmasri e Navathe, 2011).

Segundo (Elmasri e Navathe, 2011), as operações UNDO e REDO


precisam ser idempotentes ou seja, a execução de uma operação várias
vezes é equivalente a executá-la apenas uma vez. De fato, o processo
de recuperação inteiro deve ser idempotente, pois se o sistema
falhasse durante o processo de recuperação, a próxima tentativa de
recuperação poderia realizar um UNDO e um REDO certas operações
WRITE que já tinham sido executadas durante o primeiro processo
de recuperação. O resultado da recuperação de uma falha do sistema
durante a recuperação deve ser igual ao resultado da recuperação
quando não há falha durante esse processo!

5.1.2 Caching (buffering) de Blocos de Disco

O processo de recuperação em geral está bastante interligado às


funções do sistema operacional e particular, o buffering de páginas de
disco do banco de dados no cache de memória principal do SGBD.
Normalmente, várias páginas de disco que incluem os itens de dados
a serem atualizados são mantidas em cache nos buffers da memória
principal e depois atualizados na memória antes de serem gravados de
no disco. O caching de páginas de disco é tradicionalmente uma função
do sistema operacional, mas, devido a sua importância para a eficiência
dos procedimentos de recuperação, ele é tratado pelo SGBD chamando
rotinas de baixo nível do sistema operacional.
82
Prof. Eros Estevão de Moura

Em geral, é conveniente considerar a recuperação em relação às páginas


de disco (blocos) do banco de dados. Normalmente, uma coleção de
buffers memória, chamada cache do SGBD, é mantida sob o controle
do SGBD com a finalidade de manter esses buffers. Um diretório para
o cache é usado para acompanhar quais itens de banco de dados estão
nos buffers. Quando o SGBD solicita ação em algum item, primeiro ele
verifica o diretório do cache para determinar se a página de disco que
contém o item está no cache do SGBD. Se não estiver, o item precisa ser
localizado no disco, e as páginas de disco apropriadas são copiadas para
o cache. Pode ser necessário substituir (ou esvaziar) alguns dos buffers
de cache para criar espaço disponível para o novo item (no SGBD
Oracle – database buffer cache). Alguma estratégia de substituição de
página semelhante àquelas usadas nos sistemas operacionais, como a
usada menos recentemente (LRU-Least Recent Used) ou first-in-first-
out (FIFO), ou uma nova estratégia que seja específica do SGBD, pode
ser utilizada para selecionar os buffers para substituição.

As entradas no diretório de cache do SGBD mantêm informações


adicionais relevantes ao gerenciamento de buffer. Associado a cada
buffer na cache está um bit sujo, que pode ser incluído na entrada de
diretório para indicar se o buffer foi modificado ou não. Quando uma
página é lida inicialmente do disco do banco de dados para o buffer
no cache, uma nova entrada é inserida no diretório de cache com o
novo endereço de página do disco, e o bit sujo é definido como 0 (zero).
Assim que o buffer é modificado, o bit sujo para a entrada de diretório
correspondente é definido como 1 (um). Informações adicionais,
como a(s) id(s) de transação das transações que modificaram o buffer,
também podem ser mantidas no diretório. Quando o conteúdo do
buffer é substituído (esvaziado) do cache, o conteúdo primeiro precisa
ser gravado de volta à página de disco correspondente somente se seu bit
sujo for 1. Outro bit, chamado bit de preso-solto, também é necessário
(uma página no cache está presa (valor de bit 1) se ainda não puder ser
gravada de volta ao disco). Por exemplo, o protocolo de recuperação
pode impedir que certas páginas de buffer sejam gravadas no disco até
que as transações que mudaram esse buffer tenham sido confirmadas,
incluindo também a confirmação de que a transação tenha sido gravada
nos arquivos de log em disco.

Duas estratégias principais podem ser empregadas quando se esvazia


um buffer modificado para o disco. A primeira estratégia, conhecida
como atualização no local, grava o buffer no mesmo local de disco
original modificando, assim, o valor antigo de quaisquer itens de dados
alterados no disco; na prática, esta é a estratégia utilizada na maioria dos
SGBD. Logo, uma única cópia de cada bloco de disco do banco de dados
é mantida. A segunda estratégia, conhecida como sombreamento,
83
Laboratório de Banco de Dados

grava um buffer atualizado em um local diferente no disco, de modo


que múltiplas versões dos itens de dados podem ser mantidas, mas essa
técnica normalmente não é utilizada na prática.

Em geral, o valor antigo do item de dados antes da atualização é


chamado de imagem antes (BFIM — before image), e o novo valor, após
a atualização, é chamado de imagem depois (AFIM — after image). Se
o sombreamento for usado, tanto a BFIM quanto a AFIM podem ser
mantidas no disco; assim, não é estritamente necessário manter um log
para recuperação (Elmasri e Navathe, 2011). Na Seção 5.4, discutimos
rapidamente a recuperação baseada no sombreamento.

5.2 Algoritmo de recuperação ARIES

Agora, descrevemos o algoritmo ARIES como um exemplo de algoritmo


de recuperação usado em sistemas de banco de dados. Ele é utilizado em
muitos produtos relacionados ao banco de dados relacional da IBM. O
procedimento de recuperação ARIES consiste em três etapas principais:
análise, REDO e UNDO. A etapa de análise identifica as páginas sujas
(atualizadas) no buffer e o conjunto de transações ativas no momento
da falha. O ponto apropriado no log em que a operação REDO deveria
começar também é determinado. A fase de REDO na realidade reaplica
as atualizações do log ao banco de dados. Em geral, a operação REDO
é aplicada apenas a transações confirmadas. Porém, isso não acontece
no ARIES. Certas informações no log do ARIES oferecerão o ponto de
partida para o REDO, com base no qual as operações de REDO são
aplicadas até o final do log ser alcançado. Além disso, as informações
armazenadas pelo ARIES e nas páginas de dados permitirão que o
ARIES determine se a operação a ser refeita realmente foi aplicada ao
banco de dados e, portanto, não precisa ser reaplicada. Assim, somente
as operações de REDO necessárias são aplicadas durante a recuperação.
Por fim, durante a fase de UNDO, o log é varrido de trás para frente e
as operações das transações que estavam ativas no momento da falha
são desfeitas na ordem contrária. As informações necessárias para o
ARIES realizar seu procedimento de recuperação incluem o log, a tabela
de transações e a tabela de páginas sujas. Além disso, o check point é
utilizado. Essas tabelas são mantidas pelo gerenciador de transação e
gravadas no log durante o check point.

Em ARIES, cada registro de log tem um número de sequência de log


(LSN — Log Sequence Number) associado, que aumenta linearmente
com o tempo (sempre único) e indica o endereço do registro de log
no disco. Cada LSN corresponde a uma mudança específica (ação) de
84
Prof. Eros Estevão de Moura

alguma transação. Além disso, cada página de dados armazenará o


LSN do registro de log mais recente correspondente a uma mudança
para essa página. Um registro de log é gravado para qualquer uma das
seguintes ações: atualizar uma página (write), confirmar uma transação
(commit), abortar uma transação (abort), desfazer uma atualização
(undo) e encerrar uma transação (end).

Além do log, duas tabelas são necessárias para uma recuperação


eficiente: a Tabela de Transações e a Tabela de Páginas Sujas, que são
mantidas pelo gerenciador de transação. Quando ocorre uma falha,
essas tabelas são reconstruídas na fase de análise da recuperação. A
Tabela de Transações contém uma entrada para cada transação ativa,
com informações como a ID de transação, o status da transação e o LSN
do registro de log mais recente para a transação. A Tabela de Páginas
Sujas contém uma entrada para cada página suja no buffer, que inclui
a ID de página e o LSN correspondente à atualização mais antiga nessa
página. Apenas para lembrar, as páginas sujas se referem aos dados
alterados no buffer e que inda não foram gravados em disco. Maiores
detalhes sobre o algoritmo ARIES podem ser encontrados no capítulo
15 do (Date, 2003), no capítulo 17 do (Silberschattz, 2006) ou no
capítulo 23 do (Elmasri e Navathe, 2011).

5.3 Backup e recuperação de banco de


dados contra falhas catastróficas

Até aqui, todas as técnicas que discutimos se aplicam a falhas não


catastróficas. Uma suposição chave foi a de que o log do sistema é
mantido no disco e não se perde como resultado da falha. As técnicas de
recuperação que discutimos usam as entradas no log do sistema ou no
diretório de sombra (estratégia do sombreamento) para se recuperarem
da falha ao retornar o banco de dados a um estado consistente.

O gerenciador de recuperação de um SGBD também precisa ser


equipado para lidar com falhas mais catastróficas, como as falhas de
disco. A principal técnica utilizada para lidar com essas falhas é um
backup do banco de dados, em que o banco de dados inteiro e o log
são periodicamente copiados para um meio de armazenamento barato,
como fitas magnéticas ou outros dispositivos de armazenamento off-
line de grande capacidade. No caso de uma talha catastrófica do sistema,
a cópia de backup mais recente pode ser recarregada da fita para o disco,
e o sistema, reiniciado.

Os dados de aplicações críticas, como bancos, seguros, mercado de


ações e outros bancos de dados, são copiados de tempos em tempos em
85
Laboratório de Banco de Dados

sua totalidade e movidos para locais seguros e fisicamente separados.


Câmaras de armazenamento subterrâneas têm sido usadas para proteção
contra danos ocasionados por inundação, tempestade, terremoto ou
incêndio. Eventos como o ataque terrorista de 11 de setembro em Nova
York (em 2001) e o desastre do furacão Katrina em Nova Orleans (em
2005) criaram uma maior conscientização da recuperação de desastres
dos bancos de dados críticos aos negócios.

Para evitar perder todos os efeitos das transações que foram executadas
desde o último backup, é comum fazer o backup do log do sistema
em intervalos mais frequentes do que o do banco de dados inteiro,
copiando-o periodicamente para fita magnética e/ou outro disco. O
log do sistema costuma ser muito menor do que o próprio banco de
dados, e, portanto, pode ser copiado com mais frequência. Portanto,
os usuários não perdem todas as transações que realizaram desde o
último backup do banco de dados. Todas as transações confirmadas e
registradas na parte do log do sistema que foi copiada para fita podem
ter efeito sobre o banco de dados refeito. Um novo log é iniciado após
cada backup do banco de dados.

Assim, para recuperar-se da falha do disco, o banco de dados é primeiro


recriado no disco com base em sua cópia de backup mais recente em
fita. Depois disso, os efeitos de todas as transações confirmadas, cujas
operações foram registradas nas cópias do log do sistema, são refeitos.

5.4 Cold (Frio) e Hot (quente) backup

O backup cold ou frio é o backup que é feito com o banco de dados off-
-line (fora do ar). Este tipo de backup tem a vantagem de criar uma có-
pia íntegra do banco de dados, partindo do pressuposto de que o banco
de dados foi colocado off-line de maneira correta, sendo assim, foi feito
um check point e podemos ter a certeza de que esta cópia é íntegra.

Como desvantagem, há a indisponibilidade do banco de dados na jane-


la (tempo decorrido) do backup. Em algumas empresas, isso não será
problema; mas, em outras, impossível. Trabalhei em uma empresa em
que sugeri um cold backup uma vez por mês. A resposta veio através
de uma conta, resultado do custo dos sistemas parados durante a janela
de backup. Como o valor era muito alto, minha sugestão não foi aceita.

O backup hot (quente) é feito com a base de dados no ar, ou seja, com
todos os usuários podendo usar o banco de dados, e apenas se evita
fazer este backup em momentos de muita utilização do banco de dados.
86
Prof. Eros Estevão de Moura

O problema do backup hot é que, partindo do princípio de que o banco


de dados está sendo utilizado durante o backup (ele poderia estar no ar,
mas sem acesso de usuários), sempre irá precisar do log das transações
armazenada em disco (no Oracle o Redo Log File). Isso acontce porque no
momento em que começa o backup o LSN (Log Sequence Number ) é em
X, quando acaba o backup o LSN será Y e Y > X. Assim, serão necessários
arquivos de log para trazer parte do backup (início) que está em X até Y.

Como DBA (database administrator), sempre sonhei em poder todo dia


fazer um cold backup, mas a realidade das empresas nas quais trabalhei
só permitiam o hot backup.

5.5 Backup e Restore no PostgreSQL

O procedimento de backup e restore dependem de cada SGBD. Aqui


vamos tratar do caso do PostgreSQL.

Estarei abordando o básico do comando aqui. Você pode ter acesso a


todas as opções em http://www.postgresql.org/docs/9.0/static/app-
pgdump.html

5.5.1 Backup de um banco (arquivo texto SQL):

pg_dump -U <usuário> --inserts <banco> > arquivo_backup.sql

Onde:

 -U : usuário para conexão com o banco de dados;

 banco: nome do banco de dados que se deseja fazer o backup;

 --inserts: vai gerar com o comando INSERT. Este método é mais


lento e deve ser utilizado, principalmente, para migração de SGBD;

 arquivo_backup.sql: arquivo que conterá todos os SQL para


recriar as tabelas com seus dados.

Exemplo: pg_dump -U postgres --inserts db_lab_bd > banco.sql

5.5.2 Backup de um banco (pg_restore)

pg_dump –F <formato> -U <usuário> <banco> > backup_compactado.


comp
87
Laboratório de Banco de Dados

Onde:

 -F : formato do arquivo: t para arquivo compactado;

 -U : usuário para conexão com o banco de dados;

 banco: nome do banco de dados que se deseja fazer o backup;

 backup_compactado.comp: arquivo que conterá o backup


compactado que deverá ser utilizado com o pg_restore.

Exemplo:

pg_dump -F t -U eros db_lab_bd > banco.comp

OBS: dentre as várias opções não listadas aqui, há uma opção que é
–w, a qual deve ser utilizada em conjunto com o arquivo pgpass.conf
quando há necessidade de executar o comando sem passar a senha. A
senha de conexão estará no arquivo pgpass.conf. Este arquivo está em
C:\Users\Administrador\AppData\Roaming\postgresql\pgpass.conf
no Windows e na pasta base (home) do usuário no Linux/Unix.

5.5.3 Restaurando backup texto (SQL) de um banco com


o psql

psql -U <usuário> -d <banco> < <arquivo texto de backup>

Onde:

 -U : usuário para conexão com o banco de dados;

 banco: nome do banco de dados que se deseja fazer a recuperação;

 arquivo texto de backup: nome do arquivo gerado pelo pg_dump.

Exemplo:

psql -U eros -d db_lab_bd < banco.sql

5.5.4 Restaurando backup compactado de um banco com


o pg_restore

pg_restore -U <usuário> -d <banco> < <arquivo_compactado>

Onde:
88
Prof. Eros Estevão de Moura

 -U : usuário para conexão com o banco de dados;

 banco: nome do banco de dados que se deseja fazer a recuperação;

 arquivo_compactado: nome do arquivo gerado pelo pg_dump


com a opção –F t.

Exemplo:

pg_restore -U postgres -d db_lab_bd < backup_compactado.comp

5.5.5 Outros exemplos de backup em PostgreSQL

 Backup de uma tabela (compactado):

pg_dump -F t -t tab_teste -U eros <banco> > tabela.comp

 Backup de uma tabela (texto):

pg_dump -t tab_teste -U eros <banco> > tabela.sql

Qual o comando necessário para fazer um backup (utilizando o


pg_dump) com o usuário admin e com os seguintes parâmetros:

a) formato do arquivo de saída: texto


b) cópia dados utilizando comandos INSERT
c) nome do banco de dados: db_atividade
d) nome do arquivo a ser gerado: bac_db_atividade_112011.comp
e) o comando necessário para recuperar uma tabela (utilizando o
pg_restore) com os seguintes parâmetros:
• nome do banco de dados: db_atividade
• nome da Tabela a ser recuperada: cliente
• nome do arquivo a ser utilizado na recuperação: bac_db_
atividade_112011.comp
performance do
Banco de Dados

Olá!
Neste capítulo, serão apresentados conceitos básicos que estão
associados à parte de performance do banco de dados. Não é minha
intenção transformar você em um administrador de banco de dados,
desta forma não estaremos cobrindo todo o assunto associado à
performance de banco de dados. Ao final do capítulo, teremos visto:
- conceitos básicos de sintonização de desempenho de banco de
dados;
- como o SGBD processa consultas de SQL;
- sobre a importância de índices no processamento de consultas;
- sobre os tipos de decisões que o otimizador de consultas tem de
tomar;
- algumas práticas comuns utilizadas para escrever códigos eficientes
de SQL;
- como formular consultas e realizar a sintonização do SGBD para
desempenho ideal.
Bom estudo!
Prof. Eros

Uma das principais funções de um sistema gerenciador de banco de


dados é fornecer respostas aos usuários finais dentro de um tempo
adequado. Os usuários interagem com o SGBD por meio de consultas
que geram informações, utilizando a seguinte sequência:

1. a aplicação do usuário final (parte do cliente) gera uma consulta;

2. a consulta é enviada ao SGBD (parte do servidor);

3. o SGBD (parte servidor) executa a consulta;

4. o SGBD envia o conjunto de dados resultante para a aplicação do


usuário final (parte do cliente).

Os usuários finais esperam que suas consultas retornem resultados o


mais rápido possível. Mas, como se pode saber se o desempenho do
90
Prof. Eros Estevão de Moura

banco de dados é bom? Isso é difícil de avaliar. Como se pode saber


se um tempo de resposta de 1,02 segundo é bom o suficiente? É mais
fácil identificar o mau desempenho do que o bom - basta ouvir as
queixas dos usuários finais quanto à lentidão de retorno das consultas.
Infelizmente, a mesma consulta pode funcionar bem um dia e não tão
bem dois meses depois. Independente da percepção dos usuários finais,
o objetivo do desempenho de banco de dados é executar as consultas o
mais rápido possível. Portanto, esse desempenho deve ser estritamente
monitorado e passar por ajustes regulares. Segundo (Rob e Coronel,
2011), a sintonização ou tuning de desempenho de banco de dados
refere-se a um conjunto de atividades e procedimentos projetados para
reduzir o tempo de resposta de um sistema de banco de dados - ou seja,
para assegurar que uma consulta do usuário final seja processada pelo
SGBD no período mínimo de tempo.

O tempo necessário para que uma consulta retorne um conjunto


de resultados depende de vários fatores. Esses fatores tendem a ser
muito amplos e diversificados conforme o ambiente e o fornecedor. O
desempenho de um SGBD comum é restringido por três fatores principais:

 a capacidade de processamento da CPU;

 a memória principal disponível (RAM);

 a taxa de transmissão de entrada/saída (disco rígido e rede).

A Tabela 13 lista alguns componentes de sistema e resume as diretrizes


gerais para a obtenção de melhor desempenho de consultas.

Tabela 13 Resumo das diretrizes gerais para a obtenção de melhor desempenho de


consultas (Rob e Coronel, 2011)

RECURSOS DO SISTEMA CLIENTE SERVIDOR


Hardware CPU O mais rápido possível O mais rápido possível

CPU dual core ou superior Vários processadores (tecnologia


quad-core)
RAM O máximo possível O máximo possível
Disco Rígido Disco Rígido SATA/EIDE rápido, Vários 1:65536discos rígidos de alta
como espaço livre suficiente velocidade e capacidade (SCSI/SATA/
Fireware/ Fibre Channel) em configuração
RAID
Rede Conexão de alta velocidade Conexão de alta velocidade
Software Sistema Operacional Sincronização fina para melhor Sintonização fina para melhor desempenho
desempenho de aplicações de de aplicações de servidor
cliente
Rede Sintonização fina para melhor Sintonização fina para melhor taxa de
taxa de transmissão transmissão
Aplicação Otimizar SQL em aplicações de Otimizar servidor de SGBD para o melhor
cliente desempenho
91
Laboratório de Banco de Dados

Naturalmente, o sistema funcionará melhor quando seus recursos de


hardware e software estão otimizados. No entanto, no mundo real,
raramente os recursos são ilimitados. Sempre existem restrições internas
e externas. Portanto, os componentes de sistemas devem ser otimizados
para obter o melhor processamento possível com os recursos existentes
(geralmente limitados); esse é o motivo da sintonização de desempenho
de bancos de dados ser tão importante.

A boa sintonização de um sistema exige uma abordagem holística. Ou


seja, todos os fatores devem ser verificados para garantir que cada um
opere em seu nível ideal e tenha recursos suficientes para minimizar
a ocorrência de gargalos. Como o projeto de banco de dados é um
fator muito importante na determinação da eficiência de desempenho
do sistema de banco de dados, vale a pena lembrar que um bom
desempenho de banco de dados começa com um bom projeto de banco
de dados (Rob e Coronel, 2011). Não há uma sintonização refinada
que seja boa o suficiente para fazer com que um banco de dados mal
projetado funcione tão bem quanto um bem projetado.

O que constitui um projeto bom e eficiente? Do ponto de vista da


sintonização de desempenho, o projetista de banco de dados deve
assegurar que o projeto utilize os recursos disponíveis no SGBD para
garantir a integridade e o desempenho ideal do banco. Este capítulo
fornece o conhecimento básico e fundamental que poderá ajudar na
otimização do desempenho de banco de dados, da utilização de índices,
da compreensão sobre organização do armazenamento de tabelas e a
localização de dados, e da implementação da sintaxe mais eficiente de
consulta em SQL. Não estaremos abordando coisas muito importantes
como a configuração adequada do SGBD, pois este trabalho é
normalmente do administrador de banco de dados. A ideia é que, com
este conhecimento básico, você possa instalar e configurar um SGBD
para o uso mais comum.

6.1 Sintonização (tuning) de


Desempenho: Cliente e Servidor

Em geral, as atividades de sintonização de desempenho de bancos de


dados podem ser divididas entre as que ocorrem do lado do cliente e as
que ocorrem do lado do servidor:

 do lado do cliente, o objetivo é gerar uma consulta de SQL que


retorne a resposta correta no menor período de tempo, utilizando
a quantidade mínima de recursos na extremidade do servidor.
92
Prof. Eros Estevão de Moura

A atividade necessária para atingir essa meta normalmente é


chamada de sintonização (tuning) de SQL;

 do lado do servidor, o ambiente de SGBD deve ser configurado


adequadamente para responder a solicitações de clientes do modo
mais rápido possível, utilizando, de modo ideal, os recursos
existentes. As atividades necessárias para atingir essa meta
normalmente são chamadas de sintonizações (tuning) do SGBD.

Lembre-se de que as implementações de SGBD normalmente são


mais complexas do que uma simples configuração cliente/servidor
em dois níveis. No entanto, mesmo em ambientes cliente/servidor de
vários níveis (parte de interface do cliente, aplicações de middleware
e parte do servidor de banco de dados), as atividades de sintonização
de desempenho costumam ser divididas em subtarefas que garantem o
tempo de resposta mais curto entre quaisquer dois pontos componentes.

6.2 Performance de Consultas - Cliente

A sintonização de desempenho de SQL é avaliada a partir da perspectiva


do cliente. Portanto, o objetivo é ilustrar as práticas comuns utilizadas
para escrever códigos de SQL eficientes. São adequadas algumas palavras
de precaução:

 a maioria dos SGBD da atual geração executam otimização


automática de consultas na parte do servidor;

  a maioria das técnicas de otimização de desempenho de SQL


são específicas de cada SGBD e, portanto, raramente são portáteis,
mesmo entre diferentes versões do mesmo sistema. Parte do motivo
desse comportamento é o avanço constante das tecnologias de bancos
de dados.

Isso significa que você não precisa se preocupar com o modo como
a consulta será escrita, pois o SGBD sempre a otimizará? Não,
porque há um espaço considerável para aprimoramentos. (O SGBD
utiliza técnicas gerais de otimização, em vez de focar em técnicas
específicas determinadas pelas circunstâncias especiais da execução
da consulta). Uma consulta de SQL mal escrita pode colocar, e
normalmente coloca, o sistema de banco de dados de joelhos quanto
ao desempenho.

Segundo (Rob e Coronel, 2011), a maioria dos problemas atuais de


desempenho relaciona-se a código de SQL mal escrito. Portanto,
93
Laboratório de Banco de Dados

embora o SGBD forneça serviços gerais de otimização, uma consulta


escrita com cuidado sempre se sai melhor do que uma mal escrita.

Apesar de a linguagem de manipulação de SQL incluir vários comandos


(como INSERT, UPDATE, DELETE e SELECT), a maioria das
recomendações desta seção relaciona-se ao uso do comando SELECT
e, em especial, dos índices e de como escrever expressões condicionais.

Os índices constituem a técnica mais importante utilizada na otimização


de desempenho de SQL. O fundamental é saber quando utilizá-lo. Como
regra geral, os índices provavelmente serão utilizados:

 quando uma coluna indexada aparecer nos critérios de busca de


uma cláusula WHERE ou HAVING;

 quando uma coluna indexada aparecer em uma cláusula GROUP


BY ou ORDER BY;

 quando as funções MAX ou MIN forem aplicadas a uma coluna


indexada;

 quando a tivermos muitos valores diferentes dos dados da coluna


indexada (quando a esparsividade for alta).

Os índices são muito úteis quando se deseja selecionar, com base em


determinada condição, um pequeno subconjunto de linhas a partir de
uma grande tabela. Se houver um índice da coluna inserida na seleção,
o SGBD pode optar por utilizá-lo. O objetivo é criar índices com alta
seletividade. A seletividade de índices é uma medida de quão provável
um índice será utilizado no processamento de consultas. Seguem
algumas diretrizes gerais para a criação e utilização de índices:

 Crie índices para cada atributo utilizado nas cláusulas WHERE,


HAVING, ORDER BY ou GROUP BY. Criando índices para todos
os atributos utilizados em condições de busca, o SGBD acessará a
tabela utilizando varredura de índice e não varredura completa da
tabela (full table scan). Por exemplo, caso se tenha um índice para
P_PRECO (preço de produto), a condição P_PRCO > 50,00 pode
ser resolvida acessando o índice em vez da varredura sequencial de
todas as linhas da tabela e da avaliação de P_PRECO em cada linha.
Os índices também são utilizados em expressões de junção (joins),
como: funcionario.cod_depto = departamento.cod_depto.

 Não utilize índices em tabelas pequenas ou com poucos valores


distintos (pouco esparsas). Lembre-se: as tabelas pequenas e as
pouco esparsas não são a mesma coisa. Uma condição de busca em
94
Prof. Eros Estevão de Moura

tabela pouco esparsa pode retornar uma alta porcentagem de linhas


de qualquer maneira, tornando a operação do índice muito custosa
e viabilizando a varredura completa da tabela. Utilizando a mesma
lógica, não crie índices para tabelas com poucas linhas e poucos
atributos - a menos que deseje garantir a existência de valores
exclusivos em uma coluna e estrangeiras forem declaradas, pois o
otimizador utilizará os índices disponíveis no momento da junção.
(A declaração de um PK criará automaticamente um índice para a
coluna declarada.).

 Declare índices de colunas de junção que são FK. Ao realizar


operações de junção em colunas que não sejam de chave primária, é
melhor declarar os índices dessas colunas.

Quantos índices devem ser criados? Cabe repetir que não se deve criar
um índice para todos os casos a que são feitas consultas. Muitos índices
deixarão as operações INSERT, UPDATE e DELETE mais lentas,
especialmente se a tabela contiver milhares de linhas. Você deve avaliar
se o ganho com o tempo de reposta de uma consulta vale o custo de
manutenção desse índice nas operações de INSERT, UPDATE e DELETE.

Em uma empresa em que trabalhei, administrava vários SGBD, em


especial um deles era muito grande (Terabyte). Havia um relatório
que era utilizado em um departamento que demorava quase 24 horas
para acabar. Foram feitas algumas reuniões entre os usuários desse
departamento e o departamento no qual trabalhava, buscando diminuir
este tempo. Como DBA, seria simples criar um índice e fazer com que
aquele relatório rodasse em menos tempo, talvez alguma coisa perto de
6 horas, mas haveria um custo para todos os outros usuários. A questão
é de quanto em quanto tempo esse relatório era gerado. Obviamente, se
fosse diário ou semanal, teria que resolver o problema, mas, neste caso,
era mensal. Então a questão é: será que para diminuir o tempo de um
relatório mensal de 24 para 6 horas vale a pena sacrificar todos os outros
usuários todos os dias? Não. Por isso não foi criado o índice.

Para o otimizador com base em custos (utiliza estatísticas sobre a


tabela para determinar a melhor forma de acessar os dados), a resposta
mudará com o tempo, conforme novas linhas forem adicionadas
ou excluídas das tabelas. É importante avaliar constantemente a
utilização de índices: monitorá-la, testá-la, avaliá-la e aprimorá-la
se o desempenho não estiver adequado. Essa é uma das funções do
administrador de banco de dados.
95
Laboratório de Banco de Dados

6.2.1 Expressões Condicionais

Uma expressão condicional normalmente é expressa nas cláusulas


WHERE e HAVING de um comando de SQL. Também conhecida
como critério condicional, essa expressão restringe o resultado de uma
consulta apenas às linhas que atendam àa determinada condição. Em
geral, esses critérios assumem a forma apresentada na Tabela 14.

Tabela 14 Critérios Condicionais

OPERANDO 1 OPERADOR CONDICIONAL OPERANDO 2


P_PRECO > 10.00
V_ESTADO = 'ES'
NOME_CLIENTE LIKE 'Eros%'
SALARIO > SALARIO_MINIMO * 1.10

Observe, na Tabela 14, que um operando pode ser:

 um simples nome de coluna como P_PRECO e V_ESTADO;

 uma string ou uma constante, como o valor 10.00 ou o texto 'ES';

 uma expressão como SALARIO_MINIMO * 1.10.

A maioria das técnicas de otimização de consultas mencionadas a seguir


é projetada para tornar mais fácil o trabalho do otimizador. Vamos ver
como fazer expressões condicionais mais eficientes no código de SQL.

 Utilize colunas simples ou strings como operandos em uma


expressão condicional (sempre que possível evite a utilização de
expressões com funções). Comparar o conteúdo de uma única
coluna a strings é mais rápido do que comparar a expressões. Por
exemplo, P_PRECO > 10.00 é mais rápido do que SALARIO >
SALARIO_MINIMO * 1.10, pois o SGBD tem de calcular primeiro
a expressão SALARIO_MINIMO * 1.10. A utilização de funções em
expressões também adiciona o tempo total de execução de consultas.
Por exemplo, se sua condição for UPPER (NOME_CELIENTE) =
'EROS', tente utilizar NOME_CELIENTE = 'Eros' se todos os nomes
dessa coluna forem armazenados com maiúsculas e minúsculas
corretas ou a aplicação for configurada para armazenar tudo sempre
em maiúsculo.

 As comparações de campos numéricos são mais rápidas que as de


caracteres, datas e NULL. Em condições de busca, a comparação de
um atributo numérico a uma string numérica é mais rápida do que
a de um atributo de caracteres a uma string de caracteres. Em geral,
a CPU trata mais rapidamente de comparações numéricas (inteiros
96
Prof. Eros Estevão de Moura

ou decimais) do que comparações de caracteres e datas. Como os


índices não armazenam referências a valores nulos, as condições
com NULL envolvem processamento adicional e, portanto, tendem
a ser as mais lentas entre todos os operandos.

 As comparações de igualdade são mais rápidas do que as de


desigualdade. Como regra geral, as comparações de igualdade
são processadas mais rapidamente do que as comparações de
desigualdade. Por exemplo, o processamento de P_PRECO = 10.00
é mais rápido, pois o SGBD pode fazer uma busca direta utilizando
o índice da coluna. Se não houver correspondências exatas, a
condição é avaliada como falsa. No entanto, se for utilizado um
símbolo de desigualdade (>, >=, <, <=), o SGBD tem de executar
processamento adicional para concluir a solicitação. Isso ocorre
porque quase sempre haverá mais valores "maior que" ou "menor
que" do que valores exatamente "iguais a" no índice. Com exceção
de NULL, o mais lento de todos os operadores de comparação é
o LIKE como símbolos coringa, como NOME_CLIENTE LIKE
"%moura%". Além disso, a utilização do símbolo "diferente de" (< >)
resulta em buscas mais lentas, especialmente quando a esparsividade
dos dados é alta, ou seja, quando há muito mais valores diferentes
do que valores iguais.

 Sempre que possível, transforme as expressões condicionais para


utilizar strings. Por exemplo, se a condição for P_PRECO - 10 = 7,
deve ser alterada para P_PRECO = 17.

 Ao utilizar várias expressões condicionais, escreva primeiro


as condições de igualdade. Lembre-se: as condições de igualdade
são mais rápidas de processar do que as de desigualdade. Embora
a maioria dos SGBD faça isso automaticamente, prestar atenção
a esse detalhe alivia a carga do otimizador de consultas. Ele não
precisará fazer o que o usuário já fez.

  Ao utilizar várias condições AND, escreva primeiro a condição


com maior probabilidade de ser falsa. Se essa técnica for utilizada,
o SGBD interromperá a avaliação do resto das condições assim que
encontrar uma expressão condicional avaliada como falsa. Lembre-
se: para que várias condições AND sejam consideradas verdadeiras,
todas devem ser avaliadas como tal. Se uma das condições for
considerada falsa, todo o conjunto também será. Quando essa
técnica é utilizada, o SGBD não gasta tempo desnecessário avaliando
condições adicionais. Naturalmente, a utilização dessa técnica
implica um conhecimento implícito da esparsividade do conjunto
de dados. Por exemplo, veja a seguinte lista de condições:
97
Laboratório de Banco de Dados

P_PRECO > 10 AND V_ESTADO = ‘ES’

Sabendo que apenas alguns vendedores localizam-se no Espírito Santo,


pode-se reescrever essa condição como:

V_ESTADO = ‘ES’ AND P_PRECO > 10

 Ao utilizar várias condições OR, coloque primeiro a condição


com maior probabilidade de ser verdadeira. Fazendo isso, o SGBD
interromperá a avaliação das condições restantes assim que encontrar
uma expressão condicional avaliada como verdadeira. Lembre-
se: para que várias condições OR sejam consideradas verdadeiras,
apenas uma deve ser avaliada como tal.

Observação: o SGBD Oracle não avalia as consultas conforme


descrito aqui. Em vez disso, a ordem de avaliação vai da última
condição para a primeira. Você deve procurar saber em que ordem
é utilizada pelo otimizador do SGBD que está utilizando: de cima
para baixo ou de baixo para cima.

 Sempre que possível, tente evitar a utilização do operador lógico


NOT. É melhor transformar uma expressão de SQL que contenha o
operador lógico NOT em outra expressão equivalente. Por exemplo:

NOT (P_PRECO > 10.00) pode ser escrito como P_PRECO <=
10.00. Ou, NOT (E_SEXO = 'M') pode ser escrito como E_SEXO =
'F'.

6.3 Performance de SGBD - Servidor

Vamos observar agora alguns pontos que devem ser observados no lado
do servidor de banco de dados. Por favor, lembre-se de que não estou
com a pretensão de abordar tudo sobre este assunto, mas de possibilitar
uma visão básica sobre a performance do SGBD.

6.3.1 Estatísticas de Banco de Dados

Um processo do SGBD que executa um papel importante na otimização


de consultas é a coleta de estatísticas de banco de dados. O termo
estatística de banco de dados refere-se a diversas medidas sobre objetos
do banco, quantidade de registros, dispersão dos valores do índices, etc.
Essas estatísticas fornecem um retrato instantâneo das características do
banco de dados.
98
Prof. Eros Estevão de Moura

Como já vimos neste capítulo, o SGBD utiliza as estatísticas para


tomar decisões fundamentais sobre o aprimoramento da eficiência do
processamento de consultas. As estatísticas de banco de dados podem
ser coletadas através de comandos como SQL ANALYZE, que coletam
estatísticas. Além disso, vários fornecedores possuem suas próprias
rotinas para isso. Por exemplo, o DB2 da IBM utiliza o procedimento
RUNSTATS, enquanto o SQL da Microsoft aplica o UPDATE
STATISTICS e fornece as opções Auto-Update e Auto-Create Statistics
em seus parâmetros de inicialização. O importante é você saber que é
fundamental manter estas estatísticas atualizadas, do contrário, você
poderá ter um acesso lento em suas consultas. A Tabela 15 apresenta
exemplos das medidas que o SGBD pode coletar sobre diversos objetos
de banco de dados.

Tabela 15 Exemplos de medidas estatísticas de bancos de dados

OBJETO DE BANCO DE EXEMPLOS DE MEDIDAS


DADOS
Tabelas Número de linhas, Número de blocos de disco utilizados,
comprimento da linha, número de coluna em cada linha, número
de valores distintos em cada coluna, valor mínimo em cada coluna e
colunas que possuem índices.
Índices Número e nome de colunas na chave de índice, número de valores
de chave no índice, número de valores de chave distintos na chave de
índice, histograma de valores de chave em um índice e número de
páginas de disco utilizadas pelo índice.
Recursos do Ambiente Tamanho físico e lógico de blocos de disco, localização e tamanho de
arquivos de dados e número de expansões por arquivos de dados.

6.3.2 Processamento de Consultas

O que acontece na extremidade do servidor do SGBD quando o


comando de SQL do cliente é recebido? Em termos simples, o SGBD
processa uma consulta em três fases:

1. Análise sintática. O SGBD analisa a consulta de SQL e escolhe o


plano de acesso/execução mais eficiente.

2. Execução. O SGBD executa a consulta de SQL utilizando o plano


de execução escolhido.

3. Extração. O SGBD extrai os dados e envia o conjunto de resultados


de volta para o cliente.

O processamento de comandos de DDL de SQL (como CREATE


TABLE) é diferente do processamento solicitado por comandos de DML,
incluindo o comando SELECT. A diferença é que o comando de DDL,
na verdade, atualiza as tabelas de dicionário de dados ou o catálogo de
sistema, enquanto o comando de DML (SELECT, INSERT, UPDATE
99
Laboratório de Banco de Dados

e DELETE), na maioria das vezes, manipula dados do usuário final. A


Figura 6 mostra as etapas gerais necessárias para o processamento de
consultas. Cada etapa será discutida a seguir.

Figura 6 Etapas gerais necessárias para o processamento de consultas

Select ...
From ...
Where ...

Cache de SQL Cache de dados

Fase de Fase de Fase de


análise execução recuperação

Plano de acesso

• Verificação de nomenclatura • Adição de bloqueios de • Geração do conjunto


• Verificação de direitos de acesso gerenciamento de transações de resultados
• Decomposição e análise • Recuperação de blocos dos
• Geração de plano de acesso arquivos de dados
• Armazenamento do plano de • Colocação dos blocos de dados
acesso no cache no cache
• Execução das operações de E/S

Arquivos de dados

Fase de Análise do SQL

O processo de otimização inclui o desmembramento (análise)


da consulta em unidades menores e sua transformação em uma
versão ligeiramente diferente do código original, mas totalmente
equivalente e mais eficiente. Totalmente equivalente significa que os
resultados da consulta otimização são sempre iguais aos da consulta
original. Mais eficiente significa que a consulta otimizada quase
sempre será executada de modo mais rápido do que a consulta
original. (Observe que ela quase sempre é executada de modo mais
rápido, pois, como explicado anteriormente, muitos fatores afetam
o desempenho de um banco de dados. Esses fatores incluem a rede,
os recursos do computador do cliente e outras consultas sendo
executadas simultaneamente no mesmo banco.) Para determinar
o modo mais eficiente de executar a consulta, o SGBD pode
utilizar a estatística de bancos de dados sobre a qual aprendemos
anteriormente.
100
Prof. Eros Estevão de Moura

As atividades de análise do SQL são executadas pelo otimizador de


consultas, que analisa a consulta de SQL e encontra o modo mais
eficiente de acessar os dados. Esse processo constitui a fase que mais
consome tempo no processamento de consultas. A análise de uma
consulta de SQL exige diversas etapas, nas quais a consulta é:

 validada quanto à adequação sintática;

 validada em relação ao dicionário de dados para garantir que as


tabelas e nomes de colunas estejam corretos;

 validada em relação ao dicionário de dados para garantir que o


usuário tenha direitos de acesso adequados;

 analisada e decomposta em componentes mais elementares;

 otimizada pela transformação em uma consulta totalmente


equivalente, porém mais eficiente;

 preparada para execução, determinando o plano de execução ou


acesso mais eficiente.

Uma vez transformado o comando de SQL, o SGBD cria o que


normalmente se conhece como plano de acesso ou execução. O plano
de acesso é o resultado da análise de um comando de SQL. Contém a
série de etapas que o SGBD utilizará para executar a consulta e retornar
o conjunto de resultados do modo mais eficiente possível. Em primeiro
lugar, o SGBD verifica se já existe um plano de acesso para a consulta no
cache de SQL. Se existir, ele reutiliza esse plano para poupar tempo. Caso
contrário, o otimizador avalia os diferentes planos e toma decisões sobre
quais índices utilizar e como melhor executar as operações de junção.
O plano de acesso escolhido para a consulta é, em seguida, colocado no
cache de SQL e disponibilizado para uso e reuso futuro.

Observação: para ser possível a reutilização do plano de acesso, é


necessário que o SQL seja exatamente igual. Aqui lembramos a utilização
da bind variable do Oracle, que é uma técnica de programação que evita
o uso de literais nas sentenças SQL. O programador prepara a sentença
com variáveis e passa o valor para as mesmas ao invés de, literalmente,
usar o valor. A consulta nome = 'Eros' é diferente de nome = 'Moura',
mas se você enviar alguma coisa assim nome = :var_nome, independente
do conteúdo da variável, ela sempre será igual.

Esses planos são específicos de cada SGBD e traduzem a consulta de SQL


do cliente em uma série de operações de E/S complexas que leem os dados
dos arquivos físicos e geram o conjunto de resultados. Algumas operações
de E/S normalmente encontradas estão ilustradas na Tabela 16.
101
Laboratório de Banco de Dados

A Tabela 16 mostra apenas algumas operações de E/S de acesso a bancos


de dados. (Esses exemplos se baseiam no SGBD Oracle.) No entanto,
essa tabela apresenta os tipos de operações que a maioria dos SGBD
executa ao acessar e manipular conjuntos de dados.

Observe que o acesso à tabela utilizando ID de linha é o método mais


rápido. A ID de linha é uma identificação exclusiva de cada linha salva
em armazenamento permanente. Pode ser utilizada para acessar a linha
diretamente. Conceitualmente, essa ID é similar ao tíquete que se recebe
em alguns estacionamentos de aeroporto. Ele contém o número da seção
e o número da vaga. Utilizando essa informação, pode-se ir diretamente
até o carro, sem ter de procurar por todas as seções e vagas.

Tabela 16 Exemplos de operações de E/S em planos de acesso de SGBD

OPERAÇÃO DESCRIÇÃO
Varredura de Tabela (completa) Lê sequencialmente a tabela inteira, da primeira à
última linha, uma linha por vez (o processo mais
lento)
Acesso a Tabela (ID de linha) Lê diretamente uma linha de tabela utilizando um
valor de ID de linha (o processo mais rápido)
Varredura de Índice (faixa) Lê o índice primeiro para obter Ids de linhas e, em
seguida, acessa diretamente as linhas de tabelas
(processo mais rápido do que a varredura de tabela)
Acesso ao Índice (único) Utilizando quando uma tabela possui um índice
exclusivo em uma coluna
Loop Aninhado Lê e compara o conjunto de valores a outro conjunto
de valores, utilizando o estilo de loop integrado
(lento)
Fusão Funde dois conjuntos de dados (lento)
Ordenação Ordenação do conjunto de dados (lento)

Fase de Execução de SQL

Nessa fase, são executadas todas as operações de E/S indicadas no


plano de acesso. Quando essa execução ocorre, os bloqueios adequados
(se necessário) são atribuídos aos dados sendo acessados e estes são
recuperados dos arquivos de dados e colocados no cache do SGBD.
Todos os comandos de gerenciamento de transações são processados
durante as fases de análise e execução.

Fase de Recuperação do SQL

Após a conclusão das fases de análise e execução, todas as linhas que


atendam às condições especificadas são recuperadas, ordenadas,
agrupadas e/ou agregadas (se necessário). Durante a fase de recuperação,
as linhas do conjunto de resultados da consulta são reenviadas ao cliente.
102
Prof. Eros Estevão de Moura

6.3.3 Índices e Otimização de Consultas

Com já foi visto neste capítulo, os índices são fundamentais para acelerar
o acesso aos dados, pois facilitam a busca, classificação e utilização de
funções agregadas e, até mesmo, de operações de junção. A melhora da
velocidade de acesso aos dados se deve ao fato de o índice ser um conjunto
ordenado de valores que contém a chave de índice e os ponteiros. Os
ponteiros são as IDs para as linhas das tabelas reais. Conceitualmente,
o índice de dados é semelhante ao de um livro. Ao utilizar o índice de
um livro, busca-se uma palavra, que corresponde à chave de índice, e os
números de página que a acompanham, correspondentes aos ponteiros.
Estes orientam o leitor para as páginas adequadas.

A varredura de índice é mais eficiente do que a varredura completa de


uma tabela, pois os dados no índice são preordenados e sua quantidade
geralmente é muito menor (em bytes, isso quer dizer que precisamos
de menos leitura em disco e um menor espaço em memória). Portanto,
ao executar buscas, quase sempre é melhor que o SGBD utilize o índice
para acessar uma tabela e não a varredura sequencial de todas as suas
linhas (full table scan). Por exemplo, a Figura 7 mostra a representação
de índice de uma tabela CUSTOMER (cliente), como 14.786 linhas e o
índice STATE_NDX do atributo CUS_STATE (estado do cliente).

Figura 7 Representação de índice da tabela CUSTOMER (Cliente) (Rob e Coronel, 2011)

TABELA CUSTOMER (cliente)


(14.786 linhas)
ÍNDICE STATE_NDX
ID de linha CUS_CODE CUS_LNAME CUS_FNAME CUS_INITIAL CUS_AREACODE CUS_PHONE CUS_STATE CUS_BALANCE
Chave Linha 1 10010 Ramas Alfred A 615 844-2573 FL $0.00
AZ 2 2 10011 Durine Leona K 713 894-1238 AZ $0.00
..... ..... 3 10012 Smith Kathy W 615 894-2285 TX $345.86
..... .....
4 10013 Olowski Paul F 615 894-2180 AZ $536.75
FL 1
FL 7
5 10014 Orlando Myron 615 222-1672 NY $0.00
FL 8 6 10015 O’ Brian Amy B 713 442-3381 NY $0.00
FL 13245 7 10016 Brown James G 615 297-1228 FL $221.19
FL 14786 8 10017 Willians George 615 290-2556 FL $768.93
..... 9 10018 Farriss Anne G 713 382-7185 TX $216.55
..... 10 10019 Smith Olette K 615 297-3809 AZ $0.00
.... ..... ..... ..... ..... ..... ..... .....
.... ..... ..... ..... ..... ..... ..... .....
13245 23120 Veron George D 415 231-9872 FL $675.00
.... ..... ..... ..... ..... ..... ..... .....
.... ..... ..... ..... ..... ..... ..... .....
14786 24560 Suarez Victor 435 342-9876 FL $342.00

Suponha que seja enviada a seguinte consulta:

Se não houver índice, o SGBD executará uma varredura completa


da tabela, lendo, assim, 14.786 linhas de clientes. Supondo-se que
seja criado (e analisado) o índice STATE_NDX, o SGBD o utilizará
103
Laboratório de Banco de Dados

automaticamente para localizar o primeiro cliente com um estado igual


a ‘FL’ e, em seguida, prosseguirá lendo todas as linhas subsequentes de
CUSTOMER, utilizando as IDs de linha do índice (como ponteiro para o
registro) como guia. Admitindo-se que apenas cinco linhas atendessem
à condição CUS_STATE = ‘FL’, haveria cinco acessos ao índice e cinco
acessos aos dados, com um total de dez acessos de E/S. O SGBD pouparia
aproximadamente 14.776 solicitações de E/S para linhas de clientes que
não atendam ao critério. São muitos ciclos da CPU!

Se os índices são tão importantes, por que não se indexam todas as


colunas de todas as tabelas? Não é viável fazer isso. A indexação de
todas as colunas exige muito do SGBD em termos de processamento de
manutenção de índices, especialmente se a tabela tiver muitos atributos,
muitas linhas e/ou exigir muitas inserções, atualizações ou exclusões.

Uma medida que determina a necessidade de um índice é a esparsividade


dos dados da coluna que se deseja indexar. A esparsividade dos dados
refere-se ao número de valores diferentes que uma coluna pode ter. Por
exemplo, a coluna SEXO_ALUNO de uma tabela ALUNO pode ter
apenas dois valores possíveis: M ou F. Portanto, diz-se que essa coluna é
pouco esparsa. Por outro lado, a coluna DATA_NACIMENTO_ALUNO,
pode ter muitos valores diferentes, portanto, diz-se que ela é muito
esparsa. Conhecer a esparsividade ajuda a decidir sobre a utilização
de um índice adequado. Por exemplo, quando se executa uma busca
em uma coluna pouco esparsa, provavelmente será inevitável ler uma
alta porcentagem das linhas; assim sendo, o processamento de índices
pode ser um trabalho desnecessário. Neste caso o otimizador do SGBD
provavelmente não fará uso do índice.

A maioria dos SGBDs implementa índices utilizando uma das seguintes


estruturas de dados:

 Índices de hash. Utiliza-se um algoritmo para criar um valor


de hash a partir de uma coluna de chave. Esse valor aponta para
uma entrada em uma tabela de hash que, por sua vez, aponta para a
localização real da linha dos dados. Esse tipo de índice é apropriado
para operações de busca simples e rápida.

 Índices de árvore B (b-tree). Trata-se do tipo-padrão mais


comum de índice utilizado em bancos de dados. O índice de árvore B
é utilizado principalmente em tabelas nas quais os valores de coluna
repetem-se em um número relativamente menor de vezes. O índice
de árvore B é uma estrutura de dados ordenada, organizada como
uma árvore descendente. Essa árvore é armazenada separadamente
dos dados. As "folhas" de menor nível do índice contêm ponteiros
para as linhas de dados reais. Os índices de árvore B são "auto
104
Prof. Eros Estevão de Moura

equilibrados", ou seja, exigem a mesma quantidade de acessos para


encontrar qualquer linha determinada.

 Índices de bitmap. Utilizado em aplicações de dados warehouse,


para tabelas com grande número de linhas, nas quais um pequeno
número de valores de coluna se repete muitas vezes. Os índices de
bitmap tendem a utilizar menos espaço que os de árvore B, pois
utilizam bits (e não bytes) para armazenar seus dados.

Com as características de índices citadas, o projetista de bancos de


dados pode determinar o melhor tipo de índice a utilizar. Suponha,
por exemplo, uma tabela CUSTOMER (cliente) com milhares de
linhas. Essa tabela possui duas colunas utilizadas extensivamente
para consulta: CUS_LNAME (sobrenome de cliente), que representa
o sobrenome de cliente, e REGION_CODE (código de região), que
pode ter um dentre quatro valores possíveis (NE, NO, SO e SE).
Com base nessas informações, pode-se concluir que:

 como a coluna CUS_LNAME contém muitos valores diferentes


que se repetem um número relativamente pequeno de vezes (em
comparação com o número total de linhas da tabela), deve-se utilizar
um índice de árvore de índice B (b-tree);

  como a coluna REGION_CODE contém muito poucos valores


diferentes que se repetem um número relativamente grande de vezes (em
comparação com o número total de linhas da tabela), deve-se utilizar
um índice de bitmap. A Figura 8 mostra as representações de árvore B e
de bitmap para uma tabela CUSTOMER utilizada na discussão anterior.

Figura 8 Representação de índices Árvore B (b-tree) e bitmap (Rob e Coronel, 2011)

TABELA CUSTOMER (Cliente)


O índice de árvore B é utilizado em CUS_ID CUS_LNAME CUS_FNAME CUS_PHONE REGION_CODE O índice de bitmap é utilizado em
colunas de dados muito esparsas, ou 12 Adams Charlie 4533 NW colunas de dados pouco esparsas, ou
23 Blair Robert 5426 SE
seja, com muitos valores diferentes em seja, com poucos valores diferentes em
37 Coronel Carlos 2358 SW
relação ao número total de linhas. 43 DePrince Albert 6543 NE relação ao número total de linhas
55 Greer Tim 2764 SE
58 Kyle Ruben 2453 SW
62 Lee John 7895 NE
65 Maier Jerry 7689 NW
68 Morris Steve 4568 NW
72 Rob Pete 8123 NE
75 Sarver Lee 8193 SE
Índice de árvore B 80
82
Strickland
Timmons
Tomas
Douglas
3129
3499
SW
NE
Índice de bitmap
Em CUS_LNAME Em REGION_CODE
Região NE NO SE SO
- Lee + Bit 1 Bit 2 Bit 3 Bit 4 Bit... Bit...
0 1 0 0 Um byte
No índice de 0 0 1 0
bitmap, cada bit 0 0 0 1
representa um 1 0 0 0
- DePrince + - Rob + código de região. 0 0 1 0
Na primeira linha, 0 0 0 1
o bit 2 é ativado, 1 0 0 0
Adams 12 indicando, assim, 0 1 0 0
Greer 55 Mayer 65 Sarver 76
Blair 23 que o valor de 0 1 0 0
Kyle 58 Morris 68 Strickland 80
Coronel 37
Lee 82 código de região 1 0 0 0
Rob 72 Timmons 82
DePrince 43 da primeira linha 0 0 1 0
é NO. 0 0 0 1
1 0 0 0

REGION_CODE = ‘NO’
Os objetos em “folhas” contêm a chave de índice e os pontei- Cada byte índice de bitmap representa uma linha dos dados da
ros para linhas da tabela. Acessar qualquer linha, utilizando o tabela. Esses índices são muito eficientes em buscas. Por
índice, exige o mesmo número de acessos de E/S. Nesse exemplo, para encontrar todos os clientes na região NO, o
exemplo, seriam necessários quatro acessos para chegar a SGBD retornará todas as linhas com bit 2 ativado.
uma linha determinada da tabela usando o índice: um para
cada nível da árvore (objetos na “raiz”, em “ramos” e em
“folhas”) mais o acesso à linha de dados por meio do ponteiro.
105
Laboratório de Banco de Dados

Os SGBD da geração atual são inteligentes o suficiente para indicar o


melhor tipo de índice a ser utilizado sob determinadas condições (con-
tanto que o sistema tenha estatísticas atualizadas do banco de dados).
Seja qual for o índice escolhido, o SGBD define o melhor plano para
executar determinada consulta. A seguir, um exemplo simplificado do
tipo de escolha que o otimizador de consultas deve fazer.

6.3.4 Escolhas de Otimizadores

A otimização é a atividade central na fase de análise sintática do


processamento de consultas. Nessa fase, o SGBD deve escolher quais
índices utilizar, como executar operações de junção, qual tabela utilizar
primeiro, etc. Cada SGBD possui seus próprios algoritmos para a
determinação do modo mais eficiente de acessar os dados, são estes
algoritmos é que vão determinar a eficiência da consulta do SGBD. O
otimizador de consultas pode operar em dois modos:

 o otimizador, com base em regras, utiliza regras e pontos


preestabelecidos para determinar a melhor abordagem de execução
de uma consulta. As regras atribuem um "custo fixo" a cada operação
de SQL. Os custos são, em seguida, somados para produzir o custo
do plano de execução. Por exemplo, a varredura de uma tabela
completa possui um custo determinado de 10, ao passo que o acesso
à tabela por meio de uma ID de linha possui um custo determinado
de 3. Este modo não necessita da atualização das estatísticas, já
mencionada neste capítulo;

 o otimizador, com base em custos, utiliza algoritmos sofisticados


com base em estatísticas sobre os objetos a serem acessados para
determinar a melhor abordagem de execução de uma consulta. Nesse
caso, o processo do otimizador soma os custos de processamento, de
E/S e de recursos (RAM e outros espaços temporários) para obter o
custo total de determinado plano de execução.

O objetivo do otimizador é encontrar modos alternativos de executar


uma consulta, avaliar o “custo” de cada alternativa e, finalmente,
escolher aquela com o menor custo. Para compreender sua função,
utilizaremos um exemplo simples. Suponha que se queira listar todos
os produtos supridos por um fornecedor sediado na Flórida. Para obter
essa informação, seria possível escrever a seguinte consulta:
106
Prof. Eros Estevão de Moura

 A tabela PRODUCT (produto) contém 7.000 linhas.

 A tabela VENDOR (fornecedor) contém 300 linhas.

 Dez fornecedores localizam-se na Flórida.

 Mil produtos provêm de fornecedores da Flórida.

É importante observar que apenas os dois primeiros itens estão


disponíveis para o otimizador. Pressupomos os dois últimos itens
para ilustrar as escolhas que o otimizador deve fazer. Munido das
informações dos dois primeiros itens, o otimizador tentaria encontrar
o modo mais eficiente de acessar os dados. O fator principal na
determinação do melhor plano de acesso é o custo de E/S. (Lembre-se
de que o SGBD sempre tenta minimizar as operações de E/S.) A Tabela
17 mostra dois exemplos de planos de acesso da consulta anterior e
seus respectivos custos de E/S.
Tabela 17 Comparação dos planos de acesso e custos de E/S (Rob e Coronel, 2011)

PLANO ETAPA OPERAÇÃO OPERAÇÕES CUSTO DE LINHAS DO CUSTO


DE ES. ES CONJUNTO TOTAL
RESULTANTE DE ES
A A1 Produto 7.000 + 300 7.300 2.100.000 7.300
cartesiano
(PRODUCT,
VENDOR)
A2 Seleção de 2.100.000 2.100.000 7.000 2.107.300
linhas em A1
com códigos de
fornecedores
correspondentes
A3 Seleção de linhas 7.000 7.000 1.000 2.114.300
A2 com V_STATE
= 'FL'
B B1 Seleção de linhas 300 300 10 300
em VENDOR
com V_STATE
= 'FL'
B2 Produto 7.000 + 10 7.010 70.000 7.310
cartesiano
(PRODUCT, B1)
B3 Seleção de 70.000 70.000 1.000 77.310
linhas em B2
com códigos de
fornecedores
correspondentes
107
Laboratório de Banco de Dados

Para tornar os exemplos mais fáceis de serem compreendidos, as colunas


de Operações de E/S e Custo de E/S da Tabela 17 estimam apenas o
número de leituras de E/S no disco que o SGBD tem de executar. Em
nome da simplicidade, assume-se que não há índices e que cada leitura
de linha possui custo 1 de E/S. Por exemplo, na etapa Al, o SGBD deve
executar o produto cartesiano de PRODUCT e VENDOR. Para isso, é
necessário ler todas as linhas de PRODUCT (7.000) e todas as linhas
de VENDOR (300), produzindo um total de 7.300 operações de E/S.
O mesmo cálculo é feito em todas as etapas. Na Tabela 17, pode-se ver
como o plano A possui um custo total de E/S quase 30 vezes maior
do que o plano B. Nesse caso, o otimizador escolherá o plano B para
executar a SQL.

Observação: Nem todos os SGBD otimizam consultas de SQL do


mesmo modo. Por isso, leia sempre a documentação para examinar as
exigências de otimização de sua implementação de SGBD.

Dadas às condições apropriadas, algumas consultas podem ser


respondidas inteiramente utilizando apenas um índice.

Suponha, por exemplo, a tabela PRODUCT e o índice P_QOH_


NDX do atributo P_QOH (quantidade disponível). Assim, uma
consulta como SELECT MIN(P_QOH) FROM PRODUCT pode ser
solucionada lendo-se apenas a primeira entrada do índice P_QDOH_
NDX, não sendo necessário acessar nenhum dos blocos de dados da
tabela PRODUCT. (Lembre-se de que o padrão do índice é apresentar
em ordem crescente.)

6.3.5 Utilização de Sugestões (hints)

Embora o otimizador geralmente funcione muito bem na maioria das


circunstâncias, em alguns casos pode não escolher o melhor plano
de execução. Lembre-se: o otimizador toma decisões com base nas
estatísticas existentes. Se as estatísticas são antigas, é possível que o
otimizador não faça um bom trabalho na seleção do melhor plano de
execução. Mesmo com estatísticas atuais, a escolha do otimizador pode
não ser a mais eficiente. Há certas ocasiões em que o usuário final pode
querer alterar o modo do otimizador para o comando atual de SQL. Para
isso, é necessário utilizar sugestões (hints). As sugestões otimizadoras
são instruções especiais para o otimizador, embutidas no interior do
texto de comandos de SQL.

A Tabela 18 resume algumas sugestões otimizadoras mais comuns,


utilizadas no padrão de SQL.
108
Prof. Eros Estevão de Moura

Tabela 18 Sugestões (hints) otimizadoras (Rob e Coronel, 2011)

SUGESTÃO UTILIZAÇÃO
ALL_ROWS Instrui o otimizador a minimizar o tempo geral
de execução, ou seja, o tempo necessário para
retornar todas as linhas do conjunto de resultados
da consulta. Em geral, essa sugestão é utilizada
para processos em modo batch. Por exemplo:
SELECT /*+ALL_ROWS*/*
FROM PRODUCT
WHERE P_QOH < 10;
FIRST_ROWS Instrui o otimizador a minimizar o tempo
necessário para processar o primeiro conjunto de
linhas, ou seja, para retornar apenas esse primeiro
conjunto nos resultados da consulta. Em geral,
essa sugestão é utilizada para processos em modo
interativo. Por exemplo:
SELECT /*+FIRST_ROWS*/*
FROM PRODUCT
WHERE P_QOH < 10;
INDEX (nome) Faz com que o otimizador utilize o índice
P_QOH_NDX para processas essa consulta. Por
exemplo:
SELECT /*+INDEX(P_QOH_NDX) */*
FROM PRODUCT
WHERE P_QOH < 10;

6.4 Performance no PostgreSQL

Vamos ver, agora, um caso específico para colocar em prática os


conceitos vistos até aqui neste capítulo. Vamos da performance do
SQL especificamente, no SGBD PostgreSQL. Por favor, lembre-se de
que isto é específico para o PostgreSQL, por isso leia o manual do
seu SGBD para saber como trabalhar com a parte de performance
no seu caso específico.

6.4.1 Explain

Este comando mostra o plano de execução gerado pelo otimizador do


PostgreSQL para o comando fornecido. O plano de execução mostra
como as tabelas referenciadas pelo comando serão varridas (por uma
varredura sequencial simples, varredura pelo índice, etc.) e, se forem
referenciadas várias tabelas, quais algoritmos de junção serão utilizados
para juntar as linhas requisitadas de cada uma das tabelas de entrada.

Do que é mostrado, a parte mais importante é o custo estimado de


execução do comando, que é a estimativa feita pelo otimizador de quanto
tempo vai demorar para executar o comando (medido em unidades de
acesso às páginas do disco).
109
Laboratório de Banco de Dados

Na verdade, são mostrados dois números: o tempo inicial, antes que


a primeira linha possa ser retornada; o tempo total, para retornar
todas as linhas.

Para a maior parte dos comandos, o tempo total é o que importa, mas em
contextos como uma subseleção (subquery) no EXISTS, o planejador
escolhe o menor tempo inicial em vez do menor tempo total (porque o
executor vai parar após ter obtido uma linha).

Observação: lembrar que o EXISTS retorna TRUE (verdadeiro) caso


seja encontrado pelo menos 1 linha.

Além disso, se for limitado o número de linhas retornadas usando a


cláusula LIMIT, o planejador efetua uma interpolação apropriada entre
estes custos para estimar qual é realmente o plano de menor custo.

A sintaxe do comando é:

A opção ANALYZE faz o comando ser realmente executado, e não


apenas planejado.

O tempo total decorrido gasto em cada nó do plano (em milissegundos)


e o número total de linhas realmente retornadas que são adicionados ao
que é mostrado.

Esta opção é útil para ver se as estimativas do planejador estão próximas


da realidade.

Se for desejado utilizar EXPLAIN ANALYZE para um comando


INSERT, UPDATE, DELETE ou EXECUTE sem deixar o comando
afetar os dados, deve ser utilizado o seguinte procedimento:

Exemplos:

Mostrar o plano para uma consulta simples em uma tabela com uma
única coluna integer e 10.000 linhas:
110
Prof. Eros Estevão de Moura

Havendo um índice, e sendo feita uma consulta com uma condição


WHERE indexável, o comando EXPLAIN pode mostrar um plano
diferente:

O exemplo abaixo mostra o plano para uma consulta contendo uma


função de agregação:

6.4.2 Atualizando as Estatísticas no PostgreSQL

Para atualizar as estatísticas das tabelas, podemos utilizar o comando:

ANALYZE [ VERBOSE ] [ tabela [ (coluna [, ...] ) ] ]

Onde:

VERBOSE: mostra informações sobre o andamento da operação;

Coluna: você pode atualizar a estatística de apenas uma coluna

Exemplo:
Date, C. J. Introdução a Sistemas de Banco de Dados. 7. ed. Rio de Janeiro: Elsevier, 2003.

Elmasri, R.; Navathe, S. B. Sistemas de Banco de Dados. 6. ed. São Paulo: Person Addison
Wesley, 2011.

Rob, P.; Coronel, C. Sistemas de banco de dados: projeto, implementação e gerenciamento.


São Paulo: Cengage Learning, 2011.

Silberschattz, A. Sistemas de Banco de Dados. 5. ed. Rio de Janeiro: Elsevier, 2006.

Stair, R. M.; Reynolds, G. W. Princípios de Sistemas de Informação. 6. ed. São Paulo:


Cengage Learning, 2011.

Você também pode gostar