INF 70 Gerenciamento de Banco de Dados 2
INF 70 – Gerenciamento de Banco de Dados 2 Índices baseados em Hash Ilmério Reis da Silva ilmerio@facom. ufu. br www. facom. ufu. br/~ilmerio/gbd 2 UFU/FACOM/BCC
Roteiro • Fundamentos • Hash Estático • Hash Extensível • Hash Linear • Considerações Finais
Fundamentos GBD 2 3
Características • melhor desempenho em busca por igualdade na chave, mas não melhora busca por intervalo (>, <) • alguns SGBDs só implementam Árvore B+ • o Postgre. Sql implementa também Tabelas Hash • hash apresenta ganho significativo em junções Equi. Join • função hash : set of keys → set of bucket ids • Hash ideal: distribuição uniforme das entradas nos buckets • conteúdo dos buckets: alternativas (1), (2) ou (3) GBD 2 4
Função Hash Exemplo: hash(k) = h(k) mod B, onde h : set of keys → integer B : é o número de buckets disponíveis SE k é inteiro, use – h(k) = k ou – h(k) = a � k + b, sendo a e b empíricos. GBD 2 5
Classificação • Hash Estático: conjunto de buckets fixo problemas com cadeias de overflow. • Hash Dinâmico: cria buckets de forma dinâmica para evitar ou reduzir cadeias de overflow Hash Extensível: usa mais um nível de indireção diretório indexado por uma sequência de bits; havendo split, a sequência de bits cresce Hash Linear: ameniza impacto do crescimento, ’tolerando’ poucos overflows; novos buckets são criados linearmente • compromisso(trade-off) de Hash Estático x Hash Dinâmico é análogo ao compromisso ISAM x B-Tree GBD 2 6
Hash Estático GBD 2 7
Alocação de área para buckets Alocação de N páginas sucessivas no disco 0 1 2 N-1 Páginas Primárias dos Buckets Cada bucket terá entradas de dados <chave*> (Alt. 1, 2 ou 3) GBD 2 8
Alocação dinâmica de páginas de overflow Páginas de overflow são alocadas de forma dinâmica … 0 … 1 2 … N-1 Páginas Primárias dos Buckets GBD 2 Páginas de Overflow 9
Alocação dinâmica de páginas de overflow Seja k a chave do hash, então a localização do bucket será por meio da função hash … 0 … 1 2 k hash(k)=h(k) mod N … N-1 Páginas Primárias dos Buckets Páginas de Overflow Entradas do tipo <k* > GBD 2 10
Busca h(x) = x < 14* > 0 h(14) mod 6 = 2 14 hash 1 … N=6 … 2 3 4 5 Páginas Primárias dos Buckets …
Inserção Inserindo < 7* > 0 h(7) mod 6 = 1 7 hash … < 7* > 1 2 Cheia 3 4 5 Páginas Primárias dos Buckets …
Remoção Suprimindo < 25* > 0 h(25) mod 6 = 1 25 hash … < 25* > 1 2 3 4 5 Páginas Primárias dos Buckets …
Considerações finais sobre Hash Estático • • • � usualmente bucket = h(k) mod B, onde B = 2 L custo depende do tamanho das cadeias de overflow páginas primárias geralmente são contíguas no disco � bucket não é removido, mesmo ficando sem entradas � cadeia de overflow é dinâmica e degrada desempenho uma estratégia é deixar 20% de área livre nas páginas primárias GBD 2 14
Hash Extensível GBD 2 15
Evitando cadeias de overflow Solução ingênua Seja B o número de páginas primárias Solução ingênua: SE inserção em página primária cheia faça B=2 * B reorganize todos os buckets Problema: a reorganização de todos os buckets é computacionalmente cara, tornando esta solução inviável. GBD 2 16
Evitando cadeias de overflow Hash Extensível • Um diretório de ponteiros para buckets • SE inserção em página primária cheia crie um novo bucket dobre o tamanho do diretório reorganize a função hash Problema: a reorganização da função hash é um pouco complexa, mas considerando que o diretório cabe na memória, é computacionalmente viável. GBD 2 17
Diretorio de ponteiros para buckets Bucket 0 0 Bucket 1 1 2. . . N-1 Bucket 2 Contém todas as entradas <k*> tais que h(k) mod N = 1 Bucket N-1 Diretório : so armazena ponteiros para os buckets
Funcionamento • Função hash não varia • O número N de entradas no diretório varia • A medida que os buckets se enchem, estes se duplicam, e o diretório de buckets também pode duplicar. Atenção somente um bucket por vez é duplicado • Resultado: se um único bucket duplica, o diretório todo pode duplicar vários ponteiros do diretório podem apontar para o mesmo bucket só duplicam os buckets que ficam cheios. ao contrário do hash estático, registros em buckets duplicados (decorrentes de um overflow) podem ser facilmente localizados através do novo ponteiro no diretório de buckets. GBD 2 19
Exemplo Profundidade Global Profundidade Local 2 4* 12* 32* 1* 5* 2 16* Bucket A 2 00 01 21* Bucket B 2 Bucket C 10* 10 2 15* 7* 11 Diretorio 19* Paginas de dados Bucket D N = 4 = 22 Ultimos 2 digitos da representação binaria de h(k)
Inserção simples 2 Inserindo 13* 4* 12* 32* 1* 5* 2 16* 2 00 01 21* 13* 2 10* 10 2 15* 7* 11 Diretorio 19* Paginas de dados (buckets)
Inserção em bucket cheio Split do bucket 2 Inserindo 20* 4* 12* 32* 1* 5* 2 16* 2 00 01 21* 13* 2 10* 10 2 15* 7* 11 Diretorio 2 19*
Inserção em bucket cheio Duplica diretório e reorganiza da função hash Global Local 3 32* 16* 3 000 Inserindo 20* Bucket A 1 N = 8 = 23 2 001 1* 5* 21* 13* 010 011 Bucket C 2 10* 100 101 Bucket C 2 110 15* 7* 111 Diretorio 19* Bucket D 3 Bucket A 2 Ultimos 3 digitos da representação binaria de h(k)
Regra de inserção com split - Hash Extensível Sejam: pl a profundidade local e pg a profundidade global; Incrementar pl; Criar novo bucket e Redistribuir entradas de acordo com pl -ésimo bit mais significativo de hash(k); SE (pl > pg), duplicar diretório: Incrementar pg; Criar novas entradas no diretório (i. e. duplicar); Apontar novas entradas p/ buckets originais(pl-1 bits); Atualizar ponteiro que apontará para o novo bucket, de acordo com os pl bits mais significativos de hash(k). GBD 2 24
Considerações Finais – Hash Extensível • � diretório geralmente cabe na memória • � Exemplo: 100 MB em páginas de 4 K → 25000 entradas no diretório • � remoção usa processo inverso, podendo reduzir tamanho do diretório • � problema: distribuição não uniforme de chaves geram muitos splits localizados e, consequentemente, diretório pode ter crescimento exagerado. GBD 2 25
Hash Linear
Hash Linear • Não ha diretório de buckets • Pode haver páginas de overflow à medida que os buckets se enchem • Regularmente páginas de overflow são transformadas em novos buckets • Regularmente a função hash se modifica, dobrando a capacidade de endereçamento de buckets
Parâmetros e Contadores • Nivel = indica a rodada atual, a função de hash atual Inicializado com 0 • Next = bucket que deve ser dividido, se necessário Inicializado com 0 • Nm = número de buckets na rodada m N 0 = N Nm = N*2 m • Somente o bucket com número Next é dividido. Usa-se páginas de overflow para os outros buckets, se ficarem cheios. Apos divisão, Next é incrementado
Esquema Geral : rodada m next buckets divididos na rodada Bucket Next a ser dividido Buckets existentes no início da rodada m Nm = número de buckets no início da rodada m Bucket Nm + next Imagens dos buckets divididos
Inserção provocando split e avanço do next Inserção de 43* h 1 000 h 0 00 Nivel = 0 , N = 4 = 22 Next = 0 32* 44* 36* h 0(43) = 3 (11) Next = 1 001 01 9* 010 10 14* 18* 10* 30* 011 11 31* 35* 7* 00 Esta informação não é armazenada ! 25* 5* 11* 43* 44* 36* Paginas Primarias Paginas de Overflow
Busca em bucket após o next Busca de 18* h 1 000 h 0 00 Nivel = 0 , N = 4 = 22 h 0(18) = 2 (10) 32* Next = 1 001 01 9* 25* 5* 010 10 14* 18* 10* 30* 011 11 31* 35* 7* 100 00 44* 36* 11* 2 > Next = 1 Bucket 2 não foi dividido ainda 43*
Busca em bucket antes o next Busca de 32* e 44* h 1 h 0 00 Nivel = 0 , N = 4 = 22 h 0(32) = 00 h 0(44) = 00 32* Next = 1 001 01 9* 010 10 14* 18* 10* 30* 011 11 31* 35* 7* 100 00 25* 5* 11* 0 < Next Bucket 0 ja foi dividido ! 43* h 1(32) = 000 44* 36* Bucket 0 + 4 h 1(44) = 100
Inserção sem split Inserção de 37* h 0(37) = 01 000 00 32* Next = 1 001 01 9* 010 10 14* 18* 10* 30* 011 11 31* 35* 7* 100 00 25* 5* 44* 36* 37* 11* 43*
Inserção com split e incremento no next Inserção de 29* 000 00 h 0(29) = 01 32* Next =1 01 9* 010 10 14* 18* 10* 30* 011 11 31* 35* 7* 100 00 44* 36* 101 01 5* 001 25* 5* 37* 29* 37* 11* Next =2 43*
Inserção com split e mudança de rodada Inserção do 50* Nivel = 1 000 001 00 Next =0 32* h 0(50) = 10 01 9* 010 10 66* 18* 10* 34* 50* 011 11 31* 35* 11* 7* 11* 43* 100 00 44* 36* Next =3 101 01 5* 25* 37* 29* 110 10 14* 30* 22* 111 11 31* 7* h 1(50) = 010
Comparando Duplicar diretório x duplicar buckets • Passagem de hi para hi+1 no Hash Linear corresponde a duplicar o diretorio no Hash Extensível • Hash Extensível : diretório é duplicado num único passo • Hash Linear : duplicação do número de buckets se faz gradualmente
Comparando utilização de espaço nos buckets • Hash Extensível tem uma melhor ocupação dos buckets pois só se divide o bucket apropriado • Hash Linear não precisa de diretório: existe uma maneira precisa de se saber quais buckets foram divididos e quais devem ser divididos e em que circuntâncias Buckets são alocados consecutivamente: é possível localizar a página do bucket m por um simples cálculo de offsets.
Comparando Custo IO Extensível x Linear Em busca por igualdade Hash Linear tem um custo I/O menor em caso de distribuição uniforme Hash Extensível tem um custo menor em caso de distribuição não uniforme
Considerações finais sobre Hash • índices baseados em hash são os melhores para busca com predicado de igualdade • �ındices í baseados em hash não suportam busca por intervalo • � Hash estático pode resultar em longas cadeias de overflow • Hash extensível usa diretórios para controlar crescimento do hash, evitando overflow • Hash linear usa variação de função para diminuir cadeias de overflow, gerando buckets linearmente • Em geral distribuição não uniforme prejudica desempenho de índices baseados em Hash
Exercícios - Índices baseados em hash EXERCÍCIOS CAP 11 LIVRO-TEXTO GBD 2 40
FIM - Índices baseados em hash* * material baseado no livro-texto e slides da Profa. Sandra de Amo GBD 2 41
- Slides: 41