Cap. 4 Indexação Estruturada em Árvore If I had eight hours to chop down a tree, I d spent sharpening my ax. -- Abraham Lincoln Abel J.P. Gomes Bibliography: 1. R. Ramakrishnan and J. Gehrke. Database Management Systems. Addison-Wesley, 2003 (cap.10). 1
1. Objectivos Intuitivamente, o que está por detrás dos índices estruturados em árvore? Porque é que são adequados para selecções (SELECT) por gama de valores? Como é que faz pesquisa (SELECT), inserção (INSERT) e eliminação (DELETE) de registos num índice ISAM? Como é que faz pesquisa (SELECT), inserção (INSERT) e eliminação (DELETE) de registos num índice em árvore B+? Qual é o impacto de valores duplicados da chave na im plementação de índices? O que é a compressão de índices, e porque é que são importantes? O que é que acontece aos idntificadores de registos quando índices dinâmicos são actualizados? Como é que isto afecta os índices conglomerados (clustered indexes)? 2
2. Ficheiros,Páginas e Registos: uma revisão A abstracção de dados armazenados é a de ficheiros de registos. l l Registos (records) residem em páginas (pages) Physical Record ID (RID) = <page#, slot#> Dados de tamanho variável requerem estruturas mais sofisticadas para registos e páginas. (porquê?) l l registos: offset array no header páginas: Slotted pages com internal offsets & área de espaço livre Muitas vezes é melhor ser permissivo relativamente a questões como gestão de espaço livre, ordenação exacta, etc. (porquê?) Ficheiros podem ser não-ordenados (heap), ordenados, ou algum tipo de ficheiro ordenado (i.e., conglomerado ) por uma chave de pesquisa (search key). l Os compromissos são entre o custo de actualização/manutenção e a velocidade dos acessos via chave de pesquisa. l Ficheiros podem ser conglomerados (sorted) no máximo de uma maneira. Índices podem ser usados para tornar mais rápidos muitos tipos de acessos (i.e., percursos de acesso ) 3
2. Indexação: Conceitos Básicos Mecanismos de indexação usados para acelerar o acesso aos dados. l p.ex., catálogo de autores numa biblioteca Chave de pesquisa - atributo ou conjunto de atributos usados para procurar records num ficheiro. Um ficheiro de indexação ou, simplesmente, índice é constituído por records (chamados verbetes de indexação) com a seguinte forma: search-key pointer Os índices são normalmente mais pequenos que o ficheiro original Dois tipos essenciais de índices: l Índices ordenados: as chaves de pesquisa são armazenadas numa dada ordem l Índices de hashing: as chaves de pesquisa são distribuídas uniformemente por buckets usando uma hash function. 4
3. Métricas de avaliação de índices Tipos de acesso suportados eficientemente; p.ex., l records com um valor específico no atributo l ou records com um valor de atributo numa dada gama de valores. Tempo de acesso Tempo de inserção Tempo de eliminação Sobrecarga (overhead) de espaço 5
4. Índices ordenados Técnicas de indexação avaliadas com base em: Num índice ordenado, verbetes de indexação são armazenados e ordenados segundo o valor da chave de pesquisa; p.ex., catálogo de autores numa biblioteca. Índice primário: num ficheiro sequencialmente ordenado, o índice cuja chave de pesquisa especifica a ordem sequencial do ficheiro. l Também designado por índice de aglomeração l A chave de pesquisa dum índice primário é usual mas não necessariamente a chave primária. Índice secundário: um índice cuja chave de pesquisa especifica uma ordem diferente da ordem sequencial do ficheiro. Também designado por índice de não-aglomeração. Ficheiro de índice sequencial: ficheiro ordenado sequencialmente com um índice primário. 6
5. Ficheiros de indexação densos Índice denso um record de indexação aparece para todo o valor da chave de pesquisa no ficheiro. 7
Ficheiros de indexação esparsos Menos espaço e menor sobrecarga de manutenção para inserções e eliminações. Normalmente mais lento que o índice denso em localizar records. Bom compromisso: índice esparso com verbete de indexação para todo o bloco num ficheiro, correspondendo a menor valor da chave de pesquisa num bloco. 8
6. Índice Multi-nível Se índice primário não cabe na memória, o acesso torna-se dispendioso. Para reduzir o número de acessos ao disco à procura de records de indexação, trata-se índice primário mantido em disco como um ficheiro sequencial e constrói-se um índice esparso sobre ele. Índice exterior um índice esparso do índice primário Índice interior o índice primário Mesmo se o índice exterior é demasiado grande para caber na memória principal, um outro nível de indexação pode ser criado, e assim por diante. Índices de todos os níveis têm de ser actualizados face a uma inserção ou eliminação dum record dum ficheiro. 9
7. Índices Estruturados em Árvore: Introdução Técnicas de indexação estruturada em árvore suportam quer selecções por gama quer selecções por igualdade. l ISAM (Indexed Sequential Access Method): estrutura estática; tecnologia de indexação primitiva. l B+ tree: dinâmica; ajusta-se graciosamente face a inserções e eliminações. Selecções da forma field <op> constant Selecções por igualdade (op é =) l Quer índices em árvore quer índices em hashing podem ser usados, mas os índices baseados em hashing são mais eficientes. Selecções por gama (op é um de <, >, <=, >=, BETWEEN) l Índices hash não funcionam nestes casos. 10
7.1 Uma nota de precaução ISAM é uma ideia fora de moda l As árvores B+ são normalmente melhores, mas como veremos nem sempre assim é. Contudo, os índices ISAM são importantes para começar a compreender as técnicas de indexação l São mais simples que as árvores B+, mas basicamente desfrutam das mesmas ideias 11
8. Pesquisas por Gama de Valores: motivação para os índices em árvore Consideremos um ficheiro de estudantes ordenados por gpa. Encontre todos os estudantes com gpa > 3.0 l Se os dados estão num ficheiro ordenado, faça pesquisa binária para encontrar o primeiro estudante que satisfaz aquela condição; a partir daí, percorra sequencialmente o ficheiro até ao fim para encontrar todos os outros alunos. l O custo da pesquisa binária numa base de dados pode ser muito elevado. (porquê?) A ideia simples por detrás de uma solução: l crie um segundo ficheiro, chamado ficheiro de indexação (index file); l é estruturado em registos da forma <first key on page, pointer to page> cada um dos quais se refere a uma página do ficheiro (de dados) original; l É ordenado pelo atributo chave (p.e. gpa); l o formato duma página do ficheiro de indexação é o seguinte: verbete de indexação P 0 k 1 P 1 k 2 P 2 k m P m 12
8. Pesquisas por Gama: motivação para os índices em árvore(cont.) Assim, a pesquisa binária ocorre agora no ficheiro de indexação para identificar a página que contém o primeiro valor da chave (gpa) que satisfaz a selecção por gama (no nosso exemplo, o primeiro estudante com gpa>3.0). Depois, seguimos o ponteiro para a página que contém o primeiro registo de dados com aquele valor da chave. Podemos então percorrer o ficheiro de dados sequencialmente a partir daquele ponto em diante para devolver os outros registos que satisfazem a mesma condição. One-level Index Structure k1 k2 kn Ficheiro de Indexação Page 1 Page 2 Page 3 Page N Ficheiro de Dados Faz-se a pesquisa binária sobre um ficheiro de indexação que é mais pequeno do que o ficheiro de dados! 13
9. ISAM (Indexed Sequential Access Method) A possibilidade de o ficheiro de indexação ter um tamanho muito grande fez surgir a ideia da indexação em árvore. Basicamente, o que se fez foi aplicar a ideia primitiva de indexação (do acetato anterior) repetidamente por forma a criar uma estrutura de indexação multi-nível! Non-leaf Pages Leaf Pages Overflow page Primary pages Páginas-folha contêm verbetes de dados (data entries). 14
9.1 Árvore ISAM: exemplo Verbetes de indexação:<search key value, page id>; direccionam a pesquisa para os verbetes de dados existentes nas folhas da árvore. Exemplo em que cada nó tem 2 verbetes: Root 40 20 33 51 63 10* 15* 20* 27* 33* 37* 40* 46* 51* 55* 63* 97* 15
9.2 Insert: exemplo para registos cujas chaves têm os valores 23, 48, 41 e 42 Index Pages Root 40 20 33 51 63 Primary Leaf Pages 10* 15* 20* 27* 33* 37* 40* 46* 51* 55* 63* 97* Overflow Pages 23* 48* 41* 42* Assunção: cada página folha pode conter 2 verbetes 16
9.3 Delete: exemplo para os verbetes 42*, 51* e 97* Index Pages Root 40 20 33 51 63 Primary Leaf Pages 10* 15* 20* 27* 33* 37* 40* 46* 55* 63* Overflow Pages 23* 48* 41* Note que 51* aparece nos níveis de indexação, mas não no nível dos dados 17
9.4 ISAM é uma estrutura estática Estrutura estática: inserções/eliminações afectam só as páginas folha. Criação de ficheiros: páginas folha (dos dados) são alocadas sequencialmente e ordenadas pela chave de pesquisa; depois, as páginas de indexação são alocadas, seguindo-se as páginas de transbordo (overflow pages). Pesquisa: começa na raiz; usa-se comparações da chave para atravessar a árvore até à folha. Custo = log F N ; F = #verbetes/página (i.e., fanout), N = #páginas folha. Não há necessidade de ponteiros`nextleaf-page. (porquê?) Inserção: encontre a folha à qual o verbete de dados pertence, e coloque-o lá. Use uma página de transbordo se for necessário. Eliminação: encontre e remova o verbete de dados da sua folha; se a folha ficar vazia, liberte-a da memória. Data Pages Index Pages Overflow pages Page allocation in ISAM 18
9.5 ISAM: prós & contras Inserções e remoções afectam só o conteúdo das páginas folha. Contras? l Longas cadeias de transbordo podem desenvolver-se se um número significativo de inserções é feito na mesma folha tempo de devolução dum registo numa cadeia de transbordo tem um custo adicional. l Para remediar este problema, a árvore é inicialmente criada de tal modo que 20% do espaço de cada página é deixado livre. Prós? l O facto que só páginas folha são modificadas também tem uma vantagem importante relativamente ao acesso concorrente à base de dados. Assim, só as páginas folha têm de ser trancadas por forma a permitir o acesso exclusivo durante as transacções. l Esta é uma vantagem significativa relativamente a uma árvore B +. 19
10. Árvore B+: o índice mais usado Como no ISAM, todas as pesquisas atravessam a árvore desde a raiz até às folhas, mas a estrutura é dinâmica. Ela ajusta-se graciosamente a inserções e eliminações. Inserção/eliminação com um custo de log F N; mantém a árvore equilibrada-em-altura. l F = fanout, N = #páginas folha Ocupação mínima de 50% (excepto na raiz). Cada nó contém m verbetes, d m 2d; d é chamada a ordem da árvore. Suporta pesquisas por igualdade e por gama duma forma eficiente. Index Entries (to direct search) Index File double linked list Data Entries ("Sequence set") 20
10. Árvores B+: pesquisa de verbetes de dados A pesquisa começa na raiz, cabendo às comparações da chave direccioná-la para uma folha (como acontece no ISAM). Pesquisa para 5*, 15* e todos os verbetes de dados >= 24*... Root Tree order d=2 Tree height = 1 13 17 24 30 2* 3* 5* 7* 14* 16* 19* 20* 22* 24* 27* 29* 33* 34* 38* 39* Com base na pesquisa para 15*, sabemos que ele não está na árvore! 21
10. Árvores B+ Trees na Prática Ordem típica: 100. l Factor típico de preenchimento: 67%. l fanout médio= 133 Capacidades típicas: l Altura 2: 133 3 = 2,352,637 verbetes l Altura 3: 133 4 = 312,900,700 verbetes Muitas vezes mantém-se níveis de topo da árvore na buffer pool: l Nível 1 = 1 página = 8 Kbytes l Nível 2 = 133 páginas = 1 Mbyte l Nível 3 = 17,689 páginas = 133 MBytes 22
11. Algoritmo Insert de um Verbete de Dados numa Árvore B+ Encontre a folha certa L. Coloque o verbete de dados em L. l Se L tem espaço suficiente, termina! l Senão, tem de particionar L (em L e num novo nó L2) Redistribui verbetes equitativamente, e copia a chave intermédia para cima. Insere verbete de indexação que aponta para L2 no nó pai de L. Isto pode acontecer recursivamente: l Para particionar um nó de indexação, redistribua verbetes equitativamente, mas translade para cima a chave intermédia. (Faça o contraste com a partição dum nó folha.) Partições de nós fazem crescer a árvore; a partição da raiz faz crescer a árvore em altura. l Crescimento da árvore: em largura ou em altura. 23
11.1 Exemplo: inserção do verbete de dados 8* Root 13 17 24 30 2* 3* 5* 7* 14* 16* 19* 20* 22* 24* 27* 29* 33* 34* 38* 39* Root 17 5 13 24 30 2* 3* 5* 7* 8* 14* 16* 19* 20* 22* 24* 27* 29* 33* 34* 38* 39* 24
12. Partição de Página de Dados vs. Página de Indexação: do exemplo anterior relativo à inserção de 8* Observe como a ocupação mínima é garantida quer na partição duma página folha quer duma página de indexação. Note a diferença entre copiar-paracima e transladarpara-cima. 2* 3* 5* 7* 8* Partição duma Página de Dados 5 2* 3* 5* 7* Verbete a inserir no nó pai. (Note que 5 é copiado para cima e continua a aparecer na folha.) Partição duma Página de Indexação 17 5 13 17 24 30 8* Verbete a inserir no nó pai. (Note que 17 é transladado para cima e só aparece uma vez no índice.) 25
13. Algoritmo Delete dum Verbete de Dados de uma Árvore B+ Comece na raiz; encontre a folha L à qual o verbete pertence. Remova o verbete. l l Se L está pelo menos preenchida por metade, termina! Se L tem só d-1 verbetes, Tente re-distribuir verbetes entre L e o seu nó irmão (nó adjacente com o mesmo nó pai que L). Se re-distribuição falha, coalesça L com o irmão. Se ocorreu coalescência, há que eliminar verbete (apontando para L ou irmão) a partir do nó pai de L. Coalescência pode propagar-se à raiz, com a consequente diminuição da altura da árvore. 26
13.1 Exemplo: eliminação dos verbetes de dados 19* e 20* Root 17 5 13 24 30 2* 3* 5* 7* 8* 14* 16* 19* 20* 22* 24* 27* 29* 33* 34* 38* 39* Eliminação de 19* é fácil. Eliminação de 20* é feita com re-distribuição. Noltese como a chave intermédia é copiada para cima. 5 13 Root 17 27 30 2* 3* 5* 7* 8* 14* 16* 22* 24* 27* 29* 33* 34* 38* 39* 27
13.2 Exemplo: e depois eliminar o verbete de dados 24* Root 17 5 13 27 30 2* 3* 5* 7* 8* 14* 16* 22* 24* 27* 29* 33* 34* 38* 39* Eliminação de 24* é feita com coalescência das folhas. Observe o atirar fora do verbete de dados (à direita), e transladar para baixo do verbete de indexação (no acetato seguinte)... 30 22* 27* 29* 33* 34* 38* 39* 28
13.2 Exemplo (cont.): e depois a eliminação do verbete de dados 24* Root 5 13 17 30 2* 3* 5* 7* 8* 14* 16* 22* 27* 29* 33* 34* 38* 39* Eliminação de 24* é também feita com coalescência de páginas não-folha. Os exemplos anteriores ilustram o seguinte: Re-distribuição de verbetes entre folhas, e Coalescência entre páginas folha e entre páginas não-folha. Vejamos agora o quarto e último caso referente à re-distribuição de verbetes entre páginas não-folha 29
13.3 Exemplo: re-distribuição entre páginas não-folha Consideremos a árvore mostrada em baixo durante a eliminação de 24*, com a diferença que o nó não-folha que contém a chave 30 tem um nó irmão que pode dispensar verbetes (17 e 20). (Qual poderia ser a árvore inicial?) Em contraste com o exemplo anterior, podemos re-distribuir verbetes do nó filho esquerdo da raiz para o nó irmão à direita. Root 22 5 13 17 20 30 2* 3* 5* 7* 8* 14* 16* 17* 18* 20* 21* 22* 27* 29* 33* 34* 38* 39* 30
13.3 Exemplo (cont.): re-distribuição entre páginas não-folha Root 22 5 13 17 20 30 2* 3* 5* 7* 8* 14* 16* 17* 18* 20* 21* 22* 27* 29* 33* 34* 38* 39* Intuitivamente, verbetes são redistribuídos em consequência da translação do verbete de partição para o nó pai. Isto implica a re-distribuição do verbete de indexação com chave 20 para o nó irmão. 5 13 Root 17 20 22 30 2* 3* 5* 7* 8* 14* 16* 17* 18* 20* 21* 22* 27* 29* 33* 34* 38* 39* 31
14. Questões Pragmáticas das Árvores B+ Compressão de chaves Carregamento em massa (bulk-loading) duma árvore B + 32
14.1 Compressão de chaves É importante para aumentar o fan-out. (porquê?) Os valores da chave nos verbetes de indexação só direccionam o tráfego ; muitas das vezes, podemos comprimi-las. l p.e., se temos verbetes de indexação adjacentes com as chaves Dannon Yogurt, David Smith e Devarakonda Murthy, podemos abreviar David Smith para Dav. (As outras chaves podem ser comprimidas também...) É isto correcto? Não propriamente! O que acontece se exite um verbete de dados Davey Jones? (Só podemos comprimir David Smith para Davi) Em geral, durante a compressão, temos de deixar cada verbete de indexação maior do que qualquer valor da chave (em qualquer sub-árvore) à sua esquerda. Inserção/eliminação têm de ser modificadas em conformidade. 33
14.2 Carregamento em massa de uma árvore B+ Se temos uma grande colecção de registos, e queremos criar uma árvore B+ sobre algum campo ou atributo duma tabela, a inserção registo a registo torna-se uma operação muito lenta. l Também conduz à utilização mínima de folhas --- porquê? Carregamento em massa pode tornar este processo muito mais eficiente. 34
14.2 Carregamento em massa de uma árvore B+ (cont.) Initialização: ordene todos os verbetes de dados; insira ponteiro para a primeira página (folha) numa nova página que alojará a raiz. Raiz Páginas ordenadas de verbetes de dados; ainda não existentes na árvore B+ 3* 4* 6* 9* 10* 11* 12* 13* 20* 22* 23* 31* 35* 36* 38* 41* 44* 35
14.2 Carregamento em massa de uma árvore B+ (cont. 1) Verbetes de indexação para as páginas folha dão sempre entrada à direita da página de indexação mais à direita, imediatamente acima do nível de folhas. Quando fica cheio, particiona-se. (A partição pode propagar-se no sentido ascendente da árvore até à raiz.) Raiz 10 20 6 12 23 35 Páginas de verbetes de dados que ainda não estão na árvore 3* 4* 6* 9* 10* 11* 12* 13* 20* 22* 23* 31* 35* 36* 38* 41* 44* 36
14.2 Carregamento em massa de uma árvore B+ (cont.2) Muito mais rápido que inserções repetidas, em particular quando se tem em conta o trancamento (locking) de páginas para acesso exclusivo! Raiz 20 10 35 Páginas de verbetes de dados que ainda não estão na árvore 6 12 23 38 3* 4* 6* 9* 10* 11* 12* 13* 20* 22* 23* 31* 35* 36* 38* 41* 44* 37
14.2 Carregamento em massa de uma árvore B+ : sumário Opção 1: inserções múltiplas. l Lenta. l Não permite armazenamento sequencial das folhas. Opção 2: carregamento em massa l Tem vantagens no que respeita ao controlo da concorrência. l Menor número de I/Os durante a construção da árvore. l Folhas podem ser armazenadas sequencialmente (e ligadas, obviamente). l Pode controlar-se o factor de preenchimento das páginas. 38
Sumário Índices estruturados em árvore sáo ideais para pesquisas por gama, mas também são adequados para pesquisas por igualdade. ISAM é uma estrutura estática. l l Só as páginas folha são modificadas; páginas de transbordo são necessárias. Cadeias de transbordo podem degradar o desempenho, a não ser que o tamanho do conjunto de dados e a distribuição de dados permaneçam constantes. Árvore B+ é uma estrutura dinâmica. l l l l l l Inserções/eliminações deixam a árvore equilibrada em altura; o custo é log F N. Fanout (F) elevado significa que a profundidade da árvore raramente será mais do que 3 ou 4. Quase sempre melhor que manter um ficheiro ordenado. Tipicamente, 67% de ocupação média do espaço. Normalmente é preferível à ISAM, à parte das considerações de locking; ajusta-se graciosamente ao crescimento. Se os verbetes de dados são registos de dados, as partições podem mudar os rids! 39
FIM DE CAPÍTULO Sumário (cont.) A compressão de chaves aumenta o fanout, o que reduz a altura. O carregamento em massa pode tornar mais rápida a criação duma árvore B+ quando o conjunto de dados é muito grande. É o índice mais usado nos sistemas de gestão de bases de dados devido à sua versatilidade. Um dos componentes mais optimizados dum DBMS. 40