• Aucun résultat trouvé

1. LES ENTREPRISES, LE MARCHÉ ET LES BESOINS EN PERSONNEL

1.2. La qualification des entreprises

1.2.4. Les compétences du personnel

passo faz a união entre este arquivo mediano e o índice corrente de busca gerando o índice IF grande com o resultado nal contendo o índice para todas os documentos catalogados pelo sistema.

A construção do PL é realizada de outro modo. Os arquivos de transação do PL são guardados todos juntos em um mesmo repositório e o processo de release gera por completo um novo PL a cada atualização de base. Isto é feito unindo todos os arquivos pl.trans existentes.

O processo de release também lida com atualização e remoção de documentos. No PL isto é feito simplesmente removendo as entradas anteriores do arquivo de transação antigo e, no caso de atualização, armazenando as novas entradas como se fosse uma inserção normal. Para o IF, a atualização é realizada adicionando entradas que devem ser removidas no IF anterior e entradas que devem sobrepor as entradas antigas.

4.2.8 Processamento de Consultas no IF e PL

O processamento de consultas usando os índices IF e PL é realizado em duas etapas. Para uma consulta qualquer, primeiro é feito o processamento lógico da consulta para recuperar os documentos. Este processamento é realizado usando o índice IF. Nesta fase uma consulta booleana é processada gerando o conjunto com as entradas de (docid, peso) que satisfazem à consulta, onde peso é o valor de peso de ordenamento baseado no tfidf descrito na Seção 2.2.4. Este primeiro passo resolve as consultas booleanas simples.

O segundo passo acontece apenas para consultas por proximidade (Seção 3.6). Neste passo é usado o índice PL para identicar a lista de posições para cada termo presente na consulta. Para cada docid no conjunto de resposta gerado no passo anterior é calculado um novo valor de peso agora baseado na proximidade dos termos da consulta no documento.

4.3 Especicação VIF

O VIF (Vertical Inverted File) é uma estrutura de arquivo invertido com granularidade no nível de termos, compactada e com estrutura dinâmica organizada sobre uma B+-Tree.

Além disso, o VIF oferece uma API de processamento de consultas e de atualização e geração do índice.

O índice VIF é dividido em 3 estruturas. A primeira é o arquivo de dados vif.data que armazena todas as entradas VIF. Este arquivo pode ser visto como uma seqüência

4.3 Especicação VIF 58

contínua de entradas VIF em ordem crescente. Este arquivo é indexado pela segunda estrutura a vif.btree que é uma B+-Tree responsável pelo gerenciamento da disposição

dos blocos com as entradas no arquivo de dados. E a última estrutura é o vif.df que é o arquivo que armazena os valores de df de todos os termos.

Os dados armazenados no VIF são entradas de tuplas (termid, docid) associadas com o valor de peso, pesoi,j, que é um valor atribuído em tempo de indexação pelos robôs para

cada palavra-chave, e mais a lista de posições (pl) onde cada palavra ocorre no documento como descrito na Tabela 9.

Valor Descrição

termid Identicador de palavra-chave docid Identicador de documento pesotermid,docid Peso do termo no documento

size Número de vezes que o termo ocorre no documento pl Lista de posições do termo no documento

Tabela 9: Atributos de uma entrada VIF

Basicamente o VIF contém a mesma informação de um índice PL. A diferença é o atributo peso que não existia no PL. Este atributo equivale ao mesmo atributo presente no IF de peso de relevância de um documento em uma lista invertida. Este valor tem o mesmo objetivo, ser usado no cálculo do peso de relevância durante o processamento de consultas. Além disto, no VIF existe outro atributo não presente no PL. O df de cada termo é armazenado em uma estrutura separada dos dados, o vif.df.

4.3.1 Estrutura VIF

A estrutura de armazenamento dos dados se baseia no gerenciamento de blocos con- tendo partes de listas invertidas. As listas cam dispostas nos blocos, sendo que uma lista pode usar um ou mais blocos dependendo do tamanho desta. Isto é, no caso de a lista não caber em um bloco, ela é armazenada em tantos quantos forem necessários. Em caso de listas pequenas, um bloco pode conter entradas de uma ou mais listas. Esta distribuição das listas é organizada em intervalos, cada intervalo é especicado pelo limite de intervalo. Um intervalo é representado por dois pares de códigos de termo e códigos de página indicando a primeira e a última entrada do intervalo, equivalente ao PL.

A Figura 23 ilustra um exemplo da estrutura VIF onde no arquivo vif.data estão dispostas quatro entradas VIF. Cada linha mostra um exemplo de uma entrada VIF onde os dois primeiros valores separados pelo caracter : em negrito são os valores do termid

4.3 Especicação VIF 59

Figura 23: Estrutura básica índice VIF

seguido do docid da entrada, os dois valores seguintes, também separados pelo caracter : são o peso da entrada seguido de size, o tamanho da lista de posições. Em seguida seguem size valores de posicão em ordem crescente.

Nesta visão lógica toda informação aparenta estar disposta de forma contínua distri- buída entre vários blocos. Entretanto, esses blocos são distribuídos no arquivo vif.data de forma não seqüencial sendo organizados pela B+-Tree. Cada bloco tem tamanho xo

e armazena uma quantidade variável de entradas, como dito antes, esta quantidade de- pende de como as entradas foram adicionadas à estrutura onde o arquivo de dados sofre o mesmo dinamismo de um arquivo de B+-Tree. A política de atualização do arquivo

de dados é semelhante à de uma B-Tree, por isso, as duas estruturas vif.btree e vif.data podem ser vistas como uma única estrutura de uma B+-Tree onde os dados das folhas

cam armazenados no arquivo vif.data. A diferença para uma B+-Tree comum está no

uso de codicação especíco de entradas de índice invertido presente nos blocos VIF.

4.3.2 Organização blocos VIF

No VIF os blocos são organizados pela vif.btree, esta estrutura faz controle do acesso aos blocos VIF (Figura 24). Isto é feito armazenando uma chave de identicação de intervalo de cada bloco e o ponteiro do bloco semelhante ao PL. Entretanto, no VIF é necessário armazenar apenas uma entrada (termid,docid). Isto acontece porque o VIF mantém sempre todo o intervalo de cobertura das tuplas sobre controle. Como exemplo, no caso inicial um índice VIF vazio contém no vif.btree um entrada {(∞:∞)} apontando para um bloco VIF vazio na estrutura vif.data. Neste caso a entrada (∞:∞) indica, de forma implícita, que existe apenas um bloco VIF de intervalo inicial (1:1) e nal (∞,∞). Quando a estrutura ocupar dois blocos VIF então existirá duas entradas de chave no vif.btree, digamos {(t1:d1),(∞:∞)} indicando estes dois blocos identicados pelos

4.3 Especicação VIF 60

Figura 24: Organização dos blocos no VIF

O índice VIF é armazenado de forma compactada. A compactação está presente internamente nos blocos VIF na estrutura vif.data. Cada bloco é compactado indepen- dentemente dos outros onde são utilizadas as codicações Delta, VBC, Elias e Golomb descritas na Seção 3.3.1. Desta forma, a quantidade de espaço utilizado em cada bloco varia não apenas em função do número de entradas e do tamanho de cada entrada (que é variável) mas, varia também em função da taxa de compactação aplicada pelo método de compressão utilizado. Isto faz com que exista um espaço vazio variável no nal de cada bloco VIF, como ilustrado na Figura 24.

4.3.3 Processamento de Consulta no VIF

O processamento de consultas no VIF segue o modelo de processamento de expressões booleanas como descrito na Seção 3.6.1. Para que este processamento seja possível é necessário recuperar a lista invertida de um termo qualquer do índice. No VIF as entradas de uma mesma lista podem estar distribuídas de forma dispersa em diferentes blocos VIF no arquivo de dados vif.data. Desta forma, é necessário recuperar a lista de forma ordenada do índice. No VIF isto é feito em tempo de consulta. Este algoritmo de construção em tempo de consulta da lista invertida no VIF é denido da seguinte forma. Dado uma palavra-chave qualquer p primeiro deve-se recuperar o termid de p, em seguida é feita uma busca na B+-Tree para encontrar o bloco que contém a primeira entrada da lista, isto

é feito buscando na B+-Tree o intervalo da entrada (termid, 1). A B+-Tree irá retornar

um blockid que é usado para recuperar do disco o bloco VIF com as entradas que pode ou não conter a entrada buscada. O segundo passo é procurar a entrada no bloco, isto é feito fazendo uma busca binária no bloco até encontrar a primeira entrada com o termid que se procura. Deste ponto basta ler seqüencialmente as entradas do bloco até encontrar uma entrada de outro termid. Quando as entradas do bloco terminarem, então deve-se

4.3 Especicação VIF 61

recuperar o próximo bloco através da B+-Tree fazendo uma busca usando a última entrada

do bloco corrente.

4.3.4 Processamento com Fila de Prioridade

Algumas consultas podem retornar muitos itens de resposta e muitas vezes estes itens não são relevantes. Além disso, pesquisas mostram que quase a totalidade dos usuários analisam apenas os 10 ou 20 primeiros itens [57]. O custo de gerar uma lista de resposta completa não vale o esforço. Para evitar o problema de ordenar num conjunto muito extenso de itens de resposta. O processamento da busca faz a coleta das páginas relevantes usando uma la de prioridade que armazena apenas os itens de resposta com maiores pesos.

À medida que uma consulta é processada é gerada a lista de resultado com a dupla (docid, peso)onde peso é o valor de peso de relevância da página. Este peso é usado para ordenar a lista de respostas que é retornada ao usuário. Em algumas consultas podem ser retornados muitos itens. Por exemplo no nosso corpus de exemplo o termo brasil aparece em mais de um milhão de páginas. Na prática vários desses itens podem ser descartados. A la de prioridade serve para manter em memória os itens de resposta com os maiores pesos. Durante o processamento, esta la de prioridade, possibilita rapidamente descobrir o menor peso dentre os maiores. Quando uma tupla nova é processada o algoritmo verica se o peso desta tupla é maior que o menor peso na la. Se não for maior então a entrada é descartada imediatamente. Caso contrário esta entrada é adicionada à la. Se a la estiver cheia então o menor elemento é descartado.

4.3.5 Salto de Blocos

A estrutura do VIF oferece de forma nativa um índice B+-Tree que pode ser usado

para otimizar o processamento de consultas que geram muitos casamentos incorretos. Um exemplo deste tipo de consulta é a consulta brasil E izoneiro onde o termo brasil ocorre em milhões de páginas e o termo izoneiro ocorre apenas em uma dezena de páginas. O algoritmo clássico de processamento para esta consulta deveria percorrer toda a lista invertida do termo brasil. No VIF pode ser feita uma pequena modicação no processamento de consultas para saltar blocos que não possuem casamento, isto pode ser feito alterando o algoritmo de leitura seqüencial da lista invertida do termo para quando se estiver processando uma consulta do tipo E observar o maior valor de docid dos termos