Você está na página 1de 6

Atividade - Indexação - Banco de Dados II Definição das constraints:

Aluno: Luiz Ricardo Brumati De Lima


RA: 2155184
-- Primary Keys:

alter table aluno add constraint


I. EXERCÍCIO 1 ra_aluno_pk primary key (ra);
Crie as constraints que julgar necessário
após as tabelas forem criadas. Popule as alter table discip add constraint
tabelas com várias tuplas, de preferêcia sigla_discip_pk primary key (sigla);
acima de mil tuplas, até que os índices
sejam usados em suas consultas. Não se alter table matricula add constraint
esqueça de atualizar as métricas das ra_sigla_ano_semestre_matricula_pk
tabelas após a inserção (analyze). primary key (ra, sigla, ano,
semestre);
Código para criação das tabelas:
-- Foreign Keys:

CREATE TABLE Aluno(


alter table discip add constraint
Nome VARCHAR(50) NOT NULL,
RA DECIMAL(8) NOT NULL, monitor_discip_fk foreign key
DataNasc DATE NOT NULL, (monitor) references aluno (ra);
Idade DECIMAL(3),
NomeMae VARCHAR(50) NOT NULL, alter table matricula add constraint
Cidade VARCHAR(30), aluno_matricula_fk foreign key (ra)
Estado CHAR(2), references aluno (ra);
Curso VARCHAR(50),
periodo integer
alter table matricula add constraint
);
matricula_discip_fk foreign key
CREATE TABLE Discip( (sigla) references discip (sigla);
Sigla CHAR(7) NOT NULL,
Nome VARCHAR(25) NOT NULL, Os códigos aqui apresentados estão
SiglaPreReq CHAR(7),
disponíveis em atividade_indexacao.sql.
NNCred DECIMAL(2) NOT NULL,
Monitor DECIMAL(8), Cerca de 1000 tuplas foram geradas de
Depto CHAR(8) forma randômica para cada tabela com o uso
);
do código disponível em gerar_dados.py. Em
CREATE TABLE Matricula(
seguida, os comandos de inserção criados
RA DECIMAL(8) NOT NULL, foram transferidos para um único arquivo
Sigla CHAR(7) NOT NULL, (tables_population.sql) e as tabelas foram
Ano CHAR(4) NOT NULL, populadas com uma única execução do script
Semestre CHAR(1) NOT NULL, completo.
CodTurma DECIMAL(4) NOT NULL,
NotaP1 NUMERIC(3,1), Após o devido preenchimento, as métricas
NotaP2 NUMERIC(3,1), dos dados recém inseridos foram atualizadas
NotaTrab NUMERIC(3,1), por meio dos comandos:
NotaFIM NUMERIC(3,1),
Frequencia DECIMAL(3) analyze aluno;
) analyze discip;
analyze matricula;
II. EXERCÍCIO 2 III. EXERCÍCIO 3
Suponha que o seguinte índice foi criado Crie índices e mostre exemplos de
para a relação Aluno: consultas (resultados e explain) que usam
os seguinte tipos de acessos:
CREATE UNIQUE INDEX IdxAlunoNNI ON
Aluno (Nome, NomeMae, Idade); a) Sequential Scan
b) Bitmap Index Scan
a. Escreva uma consulta que utilize esse c) Index Scan
índice. d) Index-Only Scan
b. Mostre um exemplo onde o índice não
é usado mesmo utilizando algum e) Multi-Index Scan
campo indexado na cláusula where.
O primeiro passo foi a criação dos índices
utilizados em cada busca. No entanto, para a
-- Consulta que utiza o índice criado: utilização da busca com Bitmap Index, foi
explain analyze select nome, nomemae
necessária a criação da extensão adicional
from aluno where nome = 'Luiz' and
btree_gin.
nomemae = 'Marcieli';

create extension btree_gin;


create unique index IdxAlunoRaNome ON
Aluno (RA, nome);
create index IdxSiglaBitmap on
Matricula using gin (Sigla);

A busca foi realizada como Index Only, Para a busca sequencial, basta definir
visto que a cláusula where especifíca dois como parâmetro de busca qualquer campo
atributos já indexados. não indexado:

-- a) Sequential Scan
-- Consulta que não utiliza o índice
explain analyze
criado:
select ra, nome, cidade from aluno
explain analyze select nome, nomemae
where cidade = 'Curitiba';
from aluno where nomemae = 'Marcieli';

No segundo exemplo, o índice não é Como o índice IdxSiglaBitmap foi criado


utilizado pois a busca não obedece a ordem de com o método gin, o resultado é a utilização
prioridade definida na criação do índice de um índice bitmap quando realizada uma
(Nome > NomeMae > Idade). Dessa forma, é busca indexada:
necessário que o nome do aluno também seja
utilizado como critério de seleção na
pesquisa. -- b) Bitmap Index Scan
explain analyze Por fim, para o uso do Multi-Index Scan,
select sigla from matricula where basta realizar uma consulta que contenha,
sigla = 'ZCRAEPG'; pelo menos, dois atributos indexados por
índices diferentes.

-- e) Multi-Index Scan
explain analyze
select matricula.sigla, aluno.ra from
matricula, aluno
where matricula.sigla = 'ZCRAEPG' and
aluno.ra = 72435763;

Para o uso de Index Scan, é necessário que


o parâmetro da busca seja um atributo
indexado. No entanto, também requere-se que
a projeção seja realizada em pelo menos um
atributo não indexado, já que, dessa forma, o
banco de dados é obrigado a consultar a
tabela de origem.

-- c) Index Scan
explain analyze
select ra, cidade from aluno where ra
= 72435763 IV. EXERCÍCIO 4

Faça consultas com junções entre as


tabelas e mostre o desempenho criando-se
índices para cada chave estrangeira.

Ao realizar a operação do exemplo 1, é


possível observar que, por meio da busca
sequencial na tabela matrícula, o tempo de
De forma semelhantate ao item anterior, o execução é prolongado.
Index-Only Scan é utilizado quando a
projeção é realizada apenas sobre itens já
indexados, eliminando a necessidade de -- Exemplo 1:
consulta na tabela original. explain analyze
select nome, notaFIM
from matricula natural join discip
-- d) Index-Only Scan where sigla = 'ZYZZCDQ';
explain analyze
select ra, nome from aluno where ra =
72435763 and nome = 'Camila';
No entanto, com a criação do índice
IdxMatriculaSiglaFK, a busca sequencial é
substituída por uma busca indexada que reduz
o tempo de execução para 0.050ms.

create index IdxMatriculaSiglaFK on


Matricula (sigla);

V. EXERCÍCIO 5
Utilize um índice bitmap para período e
mostre-o em uso nas consultas.

A seguinte consulta foi realizada sem a


criação de nenhum índice específico:

explain analyze
Ao mesmo modo, a criação do índice select periodo from aluno
IdxDiscipMonitorFK reduz de maneira where periodo = 9;
considerável o tempo de execução ao realizar
a operação do exemplo 2, visto que este sai de
0.316ms para 0.165ms, caindo
aproximadamente pela metade:

-- Exemplo 2:
explain analyze
Em seguidam, criou-se o índice
select nome, sigla, periodo
idxAlunoPeriodo. Como já explicado
from discip natural join aluno
previamente, o índice bitmap requer a criação
where monitor = 46953510;
da extensão btree_gin, já realizada.

create index IdxAlunoPeriodo on Aluno


using gin (periodo);

create index IdxDiscipMonitorFK on Com o uso do índice, é possível notar uma


Discip (monitor); pequena redução no tempo de planejamento e
uma alteração expressiva no tempo de
execução.
VI. EXERCÍCIO 6 VII. EXERCÍCIO 7
Acrescente um campo adicional na tabela
Compare na prática o custo de executar de Aluno, chamado de informacoesExtras,
uma consulta com e sem um índice do tipo JSON. Insira dados diferentes
clusterizado na tabela aluno. Ou seja, faça telefônicos e de times de futebol que o
uma consulta sobre algum dado indexado, aluno torce para cada aluno neste JSON.
clusterize a tabela naquele índice e refaça a Crie índices para o JSON e mostre
consulta. Mostre os comandos e os consultas que o utiliza (explain analyze).
resultados do explain analyze. Exemplo: retorne os alunos que torcem para
o Internacional.
A princípio, foi criado o índice Para permitir a inserção dos novos dados
IdxAlunoNomeIdade: na tabela, a coluna adicional
informacoesExtras foi criada:
create index IdxAlunoNomeIdade ON
Aluno (nome, idade); alter table aluno
add column informacoesExtras jsonb;

Ao realizar a operação abaixo, o seguinte


resultado foi obtido: Em seguida, o código abaixo foi
desenvolvido com a própria linguagem
estrutural do SQL para gerar de forma
explain analyze randômica os novos dados:
select nome, idade from aluno
where nome = 'Luiz';
do $$
declare
table_row aluno%rowtype;
j numeric;
times varchar[] =
'{"Chapecoense","Palmeiras","São
Paulo","Internacional", "Flamengo",
"Santos","Atlético-MG","Fluminense",
"Ceará", "Corinthians", "Botafogo"}';
begin
for table_row in select * from aluno
Em seguida, a criação do cluster reordenou loop
a tabela fisicamente com base no índice j = round(random() * 10)+1;
especificado. Ao repetir a operação anterior, update aluno set informacoesExtras
os seguintes resultados foram obtidos: =
(('{
"telefone" : ' ||
cluster aluno using IdxAlunoNomeIdade; round(random()*100000000)||',
"time" : "'|| times[j] ||'"
}')::json)
where ra = table_row.ra;
end loop;
end $$
language plpgsql;

Com os campos devidamente populados, a


análise de desempenho foi realizada:
-- Ex. 1 de utilização de índices com
JSON:

explain analyze
select nome, informacoesExtras from
aluno
where informacoesExtras->>'time' =
'Internacional'; create index idxJSON on aluno using
gin
((informacoesExtras->>'telefone'));

Em seguida, foi criado o índice


idxAlunoJSONTime e a operação repetida: Vale destacar que, embora não se note uma
grande diferença prática para operações com
duração na casa de milissegundos, tais
create index idxAlunoJSONTime procedimentos tem a capacidade de reduzir
on aluno using BTREE grandes períodos de processamento em
((informacoesExtras->>'time')); bancos com uma população mais expressiva.
Uma diferença menor que 1 segundo em
uma tabela com mil tuplas pode resultar em
uma economia de horas para bancos com
milhões de dados armazenados. Portanto, o
impacto positivo do uso correto da indexação
jamais deve ser descartado.

É possível visualizar a diferença


notória de desempenho com a presença do
índice, visto que o tempo de planejamento foi
reduzido de 0.552ms para 0.071ms. Ao
mesmo passo, o tempo de execução foi de
0.111ms para 0.024ms.
O mesmo procedimento foi realizado
para o exemplo 2:

-- Ex. 2 de utilização de índices com


JSON:

explain analyze
select nome, informacoesExtras from
aluno
where informacoesExtras->>'telefone' =
'84581151';

Você também pode gostar