ISCTE – ESCOLA DE GESTÃO - Universidade Técnica de Lisboa
ISCTE – ESCOLA DE GESTÃO - Universidade Técnica de Lisboa
ISCTE – ESCOLA DE GESTÃO - Universidade Técnica de Lisboa
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
Algoritmos para a Geração <strong>de</strong> Hipercubos<br />
Análise do algoritmo Multi-Way<br />
RUI MANUEL CARVALHO DOS SANTOS CHAPOUTO<br />
Dissertação para obtenção do Grau <strong>de</strong> Mestre em<br />
ENGENHARIA INFORMÁTICA E <strong>DE</strong> COMPUTADORES<br />
Júri<br />
Presi<strong>de</strong>nte: Prof. Pedro Manuel Moreira Vaz Antunes <strong>de</strong> Sousa<br />
Orientador: Profª Cláudia Martins Antunes<br />
Vogais: Prof. Arlindo Manuel Lime<strong>de</strong> <strong>de</strong> Oliveira<br />
Profª. Helena Isabel <strong>de</strong> Jesus Galhardas<br />
Setembro 2007
Agra<strong>de</strong>cimentos<br />
Gostaria <strong>de</strong> agra<strong>de</strong>cer a todas as pessoas que, <strong>de</strong> alguma forma, directa ou indirectamente, contribuiram<br />
com comentários ou sugestões no <strong>de</strong>senvolvimento <strong>de</strong>sta tese.<br />
À minha orientadora, prof. Cláudia Antunes, a disponibilida<strong>de</strong> apresentada ao longo dos anos <strong>de</strong><br />
trabalho, em especial nas inúmeras revisões efectuadas a esta tese.<br />
Ao prof. Jiawei Han, pelas respostas prontas e precisas sempre que lhe foi solicitado ajuda no âmbito<br />
<strong>de</strong>ste projecto.<br />
Aos meus colegas <strong>de</strong> trabalho, pelo incentivo e paciência nas inúmeras vezes em que abor<strong>de</strong>i o assunto<br />
<strong>de</strong>ste trabalho ao longo <strong>de</strong>stes anos.<br />
Aos meus pais e irmã, pela confiança, incentivo e apoio incondicional, e não só, <strong>de</strong> todos estes anos.<br />
E à Rita, pela ajuda, empenho, orientação, visão crítica, companheirismo, paciência e apoio<br />
incondiconal, o meu agra<strong>de</strong>cimento muito especial.<br />
1
Resumo<br />
A tecnologia OLAP permite a um utilizador extrair e visualizar informação a partir <strong>de</strong> um conjunto <strong>de</strong><br />
dados <strong>de</strong> forma relativamente fácil e intuitiva, sob diferentes pontos <strong>de</strong> vista. Tipicamente, esta<br />
tecnologia é aplicada a nível dos sistemas <strong>de</strong> apoio à <strong>de</strong>cisão para produção <strong>de</strong> relatórios <strong>de</strong> negócios,<br />
marketing, orçamentos, previsões, relatórios financeiros e áreas similares. Para possibilitar a<br />
apresentação <strong>de</strong> diferentes vistas sobre os dados, as operações OLAP apoiam-se num mo<strong>de</strong>lo<br />
multidimensional com base no qual é construída uma ―imagem‖ dos dados, <strong>de</strong>signada como cubo. A<br />
construção <strong>de</strong>ste cubo implica o cálculo <strong>de</strong> agregados <strong>de</strong> dados multidimensionais, o que é uma tarefa<br />
com elevados requisitos a nível <strong>de</strong> tempo e espaço e para a qual foram <strong>de</strong>senvolvidos diferentes<br />
algoritmos. Um <strong>de</strong>sses algoritmos é o algoritmo Multi-Way, que se <strong>de</strong>staca dos restantes no sentido <strong>de</strong><br />
ter sido originalmente concebido para sistemas MOLAP, para os quais existem poucos algoritmos, e <strong>de</strong><br />
ter alcançado níveis <strong>de</strong> <strong>de</strong>sempenho bastante bons. O objectivo <strong>de</strong>ste trabalho passa por estudar esse<br />
algoritmo e propor para ele optimizações que lhe permitam resolver problemas que neste momento não<br />
consegue resolver, tais como a <strong>de</strong>ficiente gestão <strong>de</strong> memória.<br />
Palavras-chave: business intelligence, OLAP, mo<strong>de</strong>lo multidimensional, agregação<br />
2
Abstract<br />
OLAP technology allows a user to extract and visualize information from a data set in an easy and<br />
intuitive way, from different perspectives. Usually, this technology is used in <strong>de</strong>cision support system for<br />
report production on budgeting, previews, finantial issues and similar goals. The ability to see data from<br />
different perspectives is due to the fact that OLAP operations use a multidimensional mo<strong>de</strong>l to build an<br />
―image‖ of data, known as cube. The generation of cubes requires numerous multidimensional<br />
aggregates to be computed, which is a task with high needs of time and space. These high requisites<br />
motivated the <strong>de</strong>velopment of various algorithms, like Multi-Way algorithm. This algorithm was one of the<br />
few <strong>de</strong>veloped for MOLAP systems and shows good performances when compared with algorithms that<br />
follow other approaches. The goal of this thesis is to study that algorithm and <strong>de</strong>velop optimizations that<br />
would allow it to solve situations it is not able to hand as it was conceived, due to lack of memory.<br />
Key words: business intelligence, OLAP, multidimensional mo<strong>de</strong>l, aggregation<br />
3
Índice<br />
Lista <strong>de</strong> figuras .............................................................................................................................................. 6<br />
Lista <strong>de</strong> tabelas ............................................................................................................................................. 8<br />
Lista <strong>de</strong> abreviaturas ..................................................................................................................................... 9<br />
1 Introdução ........................................................................................................................................... 10<br />
1.1 Motivação .................................................................................................................................... 11<br />
1.2 Objectivo da tese ........................................................................................................................ 11<br />
1.3 Estrutura da tese ......................................................................................................................... 11<br />
2 Trabalhos prévios sobre geração <strong>de</strong> hipercubos ................................................................................ 13<br />
2.1 Mo<strong>de</strong>lo <strong>de</strong> dados multidimensional ............................................................................................. 13<br />
2.2 O operador DATA CUBE ............................................................................................................ 18<br />
2.3 Selecção <strong>de</strong> agregados para pré-computação ........................................................................... 21<br />
2.4 Computação <strong>de</strong> agregados multidimensionais ........................................................................... 22<br />
2.4.1 Algoritmos baseados em or<strong>de</strong>nação e dispersão (sorting e hashing) ................................ 23<br />
2.4.2 Algoritmos baseados em partição ....................................................................................... 27<br />
2.4.3 Algoritmos baseados em arrays .......................................................................................... 29<br />
2.5 Variantes ao problema tradicional............................................................................................... 42<br />
2.5.1 Computação da base para o topo (bottom-up computation) .............................................. 42<br />
2.5.2 H-cubing .............................................................................................................................. 43<br />
2.5.3 Star-Cubing ......................................................................................................................... 44<br />
3 Trabalho realizado .............................................................................................................................. 46<br />
3.1 Motivação .................................................................................................................................... 46<br />
3.2 Arquitectura ................................................................................................................................. 47<br />
3.3 Optimização <strong>de</strong> ―sub-treeing‖ ...................................................................................................... 48<br />
3.4 Optimização <strong>de</strong> ―sub-chunking‖ .................................................................................................. 50<br />
4 Estudo do algoritmo Multi-Way ........................................................................................................... 52<br />
4.1 Dados <strong>de</strong> teste ............................................................................................................................ 52<br />
4.2 Estudo do efeito da variação na <strong>de</strong>nsida<strong>de</strong> dos dados .............................................................. 53<br />
4.3 Estudo do efeito da variação do volume <strong>de</strong> dados ..................................................................... 55<br />
4
4.3.1 Efeito da variação do número <strong>de</strong> dimensões ...................................................................... 55<br />
4.3.2 Efeito da variação da cardinalida<strong>de</strong> das dimensões........................................................... 58<br />
5 Balanço final ........................................................................................................................................ 63<br />
6 Referências ......................................................................................................................................... 64<br />
5
Lista <strong>de</strong> figuras<br />
Figura 1 <strong>–</strong> Representação sob a forma <strong>de</strong> cubo 3D da tabela 2 [Han2001a] ............................................ 15<br />
Figura 2 <strong>–</strong> Malha <strong>de</strong> cubói<strong>de</strong>s para um cubo 4D [Han2001a] .................................................................... 16<br />
Figura 3 <strong>–</strong> Exemplo <strong>de</strong> um mo<strong>de</strong>lo multidimensional [Chanduri1997] ....................................................... 17<br />
Figura 4 - Operador CUBE para cubos 0D, 1D, 2D e 3D [Gray1997] ........................................................ 20<br />
Figura 5 - Malha <strong>de</strong> combinações possíveis para 3 atributos [Harinarayan1996] ...................................... 22<br />
Figura 6 <strong>–</strong> Pseudocódigo relativo ao algoritmo 2 N ...................................................................................... 23<br />
Figura 7 - Exemplo <strong>de</strong> uma malha <strong>de</strong> procura [Agrawal1996] ................................................................... 24<br />
Figura 8 - Parte da malha <strong>de</strong> procura transformada [Agrawal1996]........................................................... 25<br />
Figura 9 - Resultado obtido pelo algoritmo PipeSort para k = 1 [Agrawal1996] ......................................... 25<br />
Figura 10 - Árvore <strong>de</strong> cobertura mínima para a malha <strong>de</strong> procura apresentada na figura 7 [Agrawal1996]<br />
.................................................................................................................................................................... 26<br />
Figura 11 - Sub-árvores obtidas por partição da árvore da figura 10 segundo o atributo A [Agrawal1996]<br />
.................................................................................................................................................................... 27<br />
Figura 12 - Ilustração da lógica do funcionamento do algoritmo Partitioned-Cube [Ross1997] ................ 28<br />
Figura 13 <strong>–</strong> Pseudocódigo genérico do algoritmo Multi-Way ..................................................................... 29<br />
Figura 14 - Array 3D para as dimensões A, B e C, dividido em 64 chunks ................................................ 32<br />
Figura 15 - MMST para O = (A, B, C) [Zhao1997] ...................................................................................... 33<br />
Figura 16 - Requisitos <strong>de</strong> memória para duas or<strong>de</strong>nações diferentes das dimensões [Zhao1997] .......... 34<br />
Figura 17 <strong>–</strong> Representação <strong>de</strong> um cubo 3D segundo [Tam1998] .............................................................. 36<br />
Figura 18 <strong>–</strong> Representação do cubo C com 18 chunks [Tam1998] ........................................................... 37<br />
Figura 19 <strong>–</strong> MMST para o cubo C [Tam1998] ............................................................................................ 38<br />
Figura 20 <strong>–</strong> MNST para o cubo C [Tam1998] ............................................................................................. 39<br />
Figura 21 <strong>–</strong> Relação entre cubói<strong>de</strong>s e subcubói<strong>de</strong>s em relação à célula V(0, 0, 0) usando R-cubing<br />
[Tam1998] ................................................................................................................................................... 40<br />
Figura 22 <strong>–</strong> Processo <strong>de</strong> adição do chunk 0 aos chunks subcubói<strong>de</strong>s relacionados [Tam1998] .............. 41<br />
Figura 23 - Exemplo <strong>de</strong> uma H-tree [Agrawal1994] ................................................................................... 43<br />
Figura 24 - Árvore <strong>de</strong> computação top-down [Xin2003] ............................................................................. 44<br />
Figura 25 <strong>–</strong> Pseudocódigo correspon<strong>de</strong>nte à criação da MMST................................................................ 49<br />
Figura 26 <strong>–</strong> Exemplo <strong>de</strong> uma MMST para O = (A, B, C, D)........................................................................ 50<br />
Figura 27 - Pseudocódigo que ilustra o mecanismo <strong>de</strong> sub-chunking ...................................................... 51<br />
Figura 28 <strong>–</strong> Efeito da variação da <strong>de</strong>nsida<strong>de</strong> dos dados no número <strong>de</strong> leituras e escritas efectuadas por<br />
MW .............................................................................................................................................................. 54<br />
Figura 29 <strong>–</strong> Efeito da variação da <strong>de</strong>nsida<strong>de</strong> dos dados no tempo usado por MW para calcular o cubo 54<br />
Figura 30 <strong>–</strong> Efeito da variação do número <strong>de</strong> dimensões nas leituras e escritas realizadas para o<br />
algoritmo MW .............................................................................................................................................. 55<br />
Figura 31 <strong>–</strong> Efeito da variação do número <strong>de</strong> dimensões nas leituras e escritas realizadas ..................... 56<br />
6
Figura 32 - Efeito da variação do número <strong>de</strong> dimensões no número <strong>de</strong> nós da MMST explorados para o<br />
algoritmo MW .............................................................................................................................................. 57<br />
Figura 33 <strong>–</strong> Efeito da variação do número <strong>de</strong> dimensões no número <strong>de</strong> nós da MMST explorados ......... 57<br />
Figura 34 <strong>–</strong> Efeito da variação do número <strong>de</strong> dimensões no tempo <strong>de</strong> cálculo do cubo ........................... 58<br />
Figura 35 <strong>–</strong> Efeito da variação da cardinalida<strong>de</strong> das dimensões no número <strong>de</strong> leituras efectuadas ........ 59<br />
Figura 36 - Efeito da variação da cardinalida<strong>de</strong> das dimensões no número <strong>de</strong> escritas efectuadas ........ 59<br />
Figura 37 <strong>–</strong> Tempo consumido no cálculo do agregado pelas diferentes implementações para 2560000<br />
tuplos ........................................................................................................................................................... 60<br />
Figura 38 <strong>–</strong> Efeito da variação da cardinalida<strong>de</strong> das dimensões no tempo <strong>de</strong> cálculo do cubo ................ 61<br />
Figura 39- Comparação entre as leituras realizadas para diferentes cardinalida<strong>de</strong>s <strong>de</strong> dimensões ......... 61<br />
Figura 40 <strong>–</strong> Comparação entre as escritas realizadas para diferentes cardinalida<strong>de</strong>s <strong>de</strong> dimensões ...... 62<br />
7
Lista <strong>de</strong> tabelas<br />
Tabela 1 <strong>–</strong> Volume <strong>de</strong> vendas em função do tempo e do tipo <strong>de</strong> item para a cida<strong>de</strong> <strong>de</strong> Vancouver<br />
[Han2001a] .................................................................................................................................................. 14<br />
Tabela 2 <strong>–</strong> Volume <strong>de</strong> vendas em função do tempo, tipo <strong>de</strong> item e localização [Han2001a] .................... 14<br />
Tabela 3 <strong>–</strong> Roll-up das vendas por mo<strong>de</strong>lo, ano e cor adaptado <strong>de</strong> [Gray1997] ....................................... 18<br />
Tabela 4 - Roll-up das vendas por mo<strong>de</strong>lo, ano e cor como sugerido por Chris Date, adaptado <strong>de</strong><br />
[Gray1997]................................................................................................................................................... 19<br />
Tabela 5 - Resultado após computada a agregação, adaptado <strong>de</strong> [Gray1997] ......................................... 19<br />
Tabela 6 - Linhas a acrescentar à tabela 3 adaptado <strong>de</strong> [Gray1997] ........................................................ 19<br />
Tabela 7 - Cross table para as vendas da marca Chevy adaptado <strong>de</strong> [Gray1997].................................... 20<br />
Tabela 8 <strong>–</strong> Or<strong>de</strong>m das células do cubo no array [Tam1998] ...................................................................... 36<br />
Tabela 9 <strong>–</strong> Exemplo <strong>de</strong> notação utilizada para i<strong>de</strong>ntificar os agregados e seus elementos ...................... 48<br />
Tabela 10 <strong>–</strong> Plano <strong>de</strong> testes ....................................................................................................................... 53<br />
8
Lista <strong>de</strong> abreviaturas<br />
BUC Bottom-Up Computation<br />
mDC Mínimo divisor comum<br />
MDC Máximo divisor comum<br />
MMST Minimum Memory Spanning Tree<br />
MNST Minimum Number Spanning Tree<br />
MOLAP Multidimensional On-Line Analytical Processing<br />
MW Multi-Way Array<br />
OLAP On-Line Analytical Processing<br />
ROLAP Relational On-Line Analytical Processing<br />
SC Sub-Chunking<br />
ST Sub-Treeing<br />
SQL Structured Querying Language<br />
9
1 Introdução<br />
Ao longo das últimas décadas, as nossas capacida<strong>de</strong>s <strong>de</strong> gerar, recolher e coleccionar dados têm<br />
aumentado <strong>de</strong> forma significativa. A investigação crescente na área das tecnologias <strong>de</strong> informação e<br />
sistemas <strong>de</strong> bases <strong>de</strong> dados <strong>de</strong>s<strong>de</strong> a década <strong>de</strong> 70, associada ao custo cada vez menor e consequente<br />
vulgarização dos recursos <strong>de</strong> hardware, tornou prática relativamente comum o armazenamento <strong>de</strong><br />
diferentes tipos <strong>de</strong> dados em estruturas relacionais. Consequentemente, a maioria das organizações<br />
começou a manter dados sobre os seus eventos, activida<strong>de</strong>s e clientes, tais como inventários, históricos<br />
<strong>de</strong> vendas, fichas <strong>de</strong> clientes, dados sobre o mercado, entre outros. O facto <strong>de</strong> efectuar esta<br />
armazenagem po<strong>de</strong> ser convertido numa vantagem competitiva, <strong>de</strong>s<strong>de</strong> que os dados sejam analisados<br />
criteriosamente e com rigor, por forma a extrair <strong>de</strong>les informação útil. Porém, a quantida<strong>de</strong> <strong>de</strong> dados<br />
acumulados atingiu gran<strong>de</strong>s dimensões e cresceu muito rapidamente, pelo que exce<strong>de</strong>u a capacida<strong>de</strong><br />
humana para os compreen<strong>de</strong>r e analisar. Por esta razão, as <strong>de</strong>cisões não eram realmente tomadas com<br />
base na informação oculta nas bases <strong>de</strong> dados, dando origem a uma situação <strong>de</strong>signada como ―data rich<br />
but information poor‖ [Han2001a].<br />
Assim sendo, as exigências do mundo mo<strong>de</strong>rno e em constante mudança levaram à criação <strong>de</strong> várias<br />
técnicas e ferramentas para auxiliar os indivíduos encarregues das tomadas <strong>de</strong> <strong>de</strong>cisão nessa tarefa. A<br />
partir da década <strong>de</strong> 80, a área das tecnologias <strong>de</strong> informação verificou novamente um gran<strong>de</strong><br />
crescimento, com a adopção generalizada do mo<strong>de</strong>lo relacional e a intensificação da investigação na<br />
área das bases <strong>de</strong> dados, nomeadamente a nível dos mo<strong>de</strong>los <strong>de</strong> dados e <strong>de</strong> bases <strong>de</strong> dados<br />
orientados a aplicações e/ou fins específicos. Devido ao surgimento e expansão da Internet, a<br />
investigação nesta área passou a focar igualmente temas relacionados com a distribuição, partilha <strong>de</strong><br />
dados e a heterogeneida<strong>de</strong> das bases <strong>de</strong> dados. Surgiram, assim, sistemas sofisticados <strong>de</strong> apoio à<br />
<strong>de</strong>cisão que permitiram às organizações agilizar e tornar mais eficiente o processo <strong>de</strong> tomada <strong>de</strong><br />
<strong>de</strong>cisões com base nos dados armazenados. O termo datawarehousing refere-se exactamente a um<br />
conjunto <strong>de</strong> tecnologias <strong>de</strong> suporte à <strong>de</strong>cisão que possibilitam a análise da informação oculta pela<br />
quantida<strong>de</strong> <strong>de</strong> dados. Como as bases <strong>de</strong> dados operacionais estão organizadas no sentido <strong>de</strong> optimizar<br />
o uso diário e normalmente é necessária a consolidação <strong>de</strong> dados <strong>de</strong> diferentes fontes para fins <strong>de</strong><br />
suporte à <strong>de</strong>cisão, as datawarehouses são preferidas em relação às bases <strong>de</strong> dados correntes pelo facto<br />
<strong>de</strong> conterem registos históricos que agregam dados <strong>de</strong> diferentes fontes. Este tipo <strong>de</strong> repositório po<strong>de</strong><br />
ser implementado sobre os sistemas <strong>de</strong> gestão <strong>de</strong> base <strong>de</strong> dados relacionais, recorrendo a extensões <strong>de</strong><br />
SQL e métodos próprios para implementar as operações necessárias <strong>de</strong> forma eficiente. Porém, existe<br />
um outro tipo <strong>de</strong> data warehouses que implementam o mo<strong>de</strong>lo <strong>de</strong> dados multidimensional, no qual os<br />
dados são representados na forma <strong>de</strong> um cubo, implementados em estruturas especiais (por exemplo,<br />
arrays).<br />
In<strong>de</strong>pen<strong>de</strong>ntemente do tipo <strong>de</strong> implementação, um aspecto fulcral na análise <strong>de</strong> dados organizados<br />
segundo o mo<strong>de</strong>lo multidimensional é a computação eficiente <strong>de</strong> agregações segundo várias dimensões<br />
do cubo, ou seja, a computação dos vários cubói<strong>de</strong>s que compõem um cubo. Os algoritmos concebidos<br />
10
para este fim <strong>de</strong>vem levar em conta a quantida<strong>de</strong> <strong>de</strong> memória que po<strong>de</strong> ser consumida na computação<br />
dos agregados e o tempo dispendido. Apesar do interesse generalizado em torno dos sistemas <strong>de</strong> apoio<br />
à <strong>de</strong>cisão e tecnologias relacionadas, a discussão aberta sobre estes algoritmos não é uma área<br />
privilegiada <strong>de</strong> investigação académica. A maioria das implementações <strong>de</strong>stes algoritmos faz parte <strong>de</strong><br />
soluções <strong>de</strong> business intelligence <strong>de</strong>senvolvidas para comercialização e, como tal, não estão acessíveis.<br />
1.1 Motivação<br />
O uso crescente <strong>de</strong> ferramentas <strong>de</strong> apoio à <strong>de</strong>cisão faz com que as questões relacionadas com as data<br />
warehouses e o mo<strong>de</strong>lo multidimensional sejam importantes, na medida em que <strong>de</strong>terminam o<br />
<strong>de</strong>sempenho <strong>de</strong>ssas ferramentas e a qualida<strong>de</strong> dos resultados obtidos. O objectivo dos cubos é<br />
permitirem ao utilizador uma forma rápida e flexível <strong>de</strong> olhar para os dados. Neste caso, a exploração<br />
dos dados é conduzida pelo utilizador no sentido em que este não sabe à partida aquilo que quer<br />
encontrar. Existem diferentes técnicas para realizar a computação <strong>de</strong> agregados multidimensionais,<br />
sendo cada uma <strong>de</strong>las mais a<strong>de</strong>quada a <strong>de</strong>terminados problemas, e não existe uma técnica universal.<br />
Além da complexida<strong>de</strong> inerente à computação dos agregados, um dos principais problemas que se<br />
põem a estes algoritmos é o carácter dos dados, que muitas vezes são esparsos e po<strong>de</strong>m reduzir a<br />
eficiência <strong>de</strong> um algoritmo se isso não for levado em conta. Logo, os principais <strong>de</strong>safios nesta área<br />
consistem na implementação dos algoritmos <strong>de</strong> forma a que sejam eficientes e permitam obter<br />
resultados no menor espaço <strong>de</strong> tempo possível. Com efeito, a implementação po<strong>de</strong> fazer toda a<br />
diferença no <strong>de</strong>sempenho <strong>de</strong>ste tipo <strong>de</strong> algoritmos.<br />
1.2 Objectivo da tese<br />
Devido ao facto <strong>de</strong> o algoritmo Multi-Way, se apresentar como um dos mais promissores, optou-se por<br />
aprofundar o seu estudo. Assim, o objectivo <strong>de</strong>ste trabalho consiste em estudar aprofundadamente o<br />
algoritmo Multi-Way, assim como uma sua variante disponibilizada no sistema DBMiner, por forma a<br />
i<strong>de</strong>ntificar as suas limitações face a bases <strong>de</strong> dados com características variadas. Na sequência <strong>de</strong>sse<br />
estudo, foram propostas duas optimizações que lhe permitem ser aplicado com maior sucesso num<br />
maior número <strong>de</strong> situações. Esta tese formaliza a proposta <strong>de</strong>ssas optimizações e relata os resultados<br />
obtidos pelo algoritmo na presença e ausência daquelas optimizações.<br />
1.3 Estrutura da tese<br />
A tese encontra-se organizada da seguinte forma: a secção 2 <strong>de</strong>screve a investigação realizada no<br />
domínio dos algoritmos para geração <strong>de</strong> hipercubos, com especial incidência no algoritmo Multi-Way; a<br />
secção 3 apresenta o trabalho realizado, <strong>de</strong>finindo o problema que se preten<strong>de</strong> estudar no contexto dos<br />
trabalhos prévios na área e <strong>de</strong>screvendo a implementação e as optimizações propostas ao algoritmo<br />
11
Multi-Way; a secção 4 apresenta os resultados dos testes realizados para aferir o <strong>de</strong>sempenho do<br />
algoritmo numa varieda<strong>de</strong> <strong>de</strong> dados e em simultâneo avaliar o real impacto das optimizações propostas;<br />
por fim, a secção 5 faz um balanço do trabalho realizado.<br />
12
2 Trabalhos prévios sobre geração <strong>de</strong> hipercubos<br />
Esta secção apresenta os trabalhos já realizados na área <strong>de</strong> geração <strong>de</strong> hipercubos e OLAP, com<br />
especial relevância para os problemas que se põem ao cálculo <strong>de</strong> agregados multidimensionais e aos<br />
vários algoritmos que foram concebidos para ultrapassar estes problemas.<br />
2.1 Mo<strong>de</strong>lo <strong>de</strong> dados multidimensional<br />
Com a crescente quantida<strong>de</strong> <strong>de</strong> dados disponíveis, o recurso a data warehouses torna-se cada vez mais<br />
necessário e frequente. Apesar disso, o conceito <strong>de</strong> data warehouse não tem uma <strong>de</strong>finição única.<br />
Normalmente, o termo é utilizado para referir uma base <strong>de</strong> dados que é mantida separada da base <strong>de</strong><br />
dados operacional <strong>de</strong> uma organização e que está integrada com vários sistemas que permitem efectuar<br />
o processamento e análise dos dados. Uma das <strong>de</strong>finições mais usadas <strong>de</strong>fen<strong>de</strong> que a data warehouse<br />
é um conjunto <strong>de</strong> dados organizados em torno <strong>de</strong> um <strong>de</strong>terminado tópico, resultante da integração <strong>de</strong><br />
diferentes fontes <strong>de</strong> dados, mantidos <strong>de</strong> forma persistente e que expressa uma perspectiva histórica<br />
<strong>de</strong>sses dados. Segundo Inmon, o conceito <strong>de</strong> data warehouse po<strong>de</strong> ser <strong>de</strong>finido como um conjunto<br />
integrado e não-volátil <strong>de</strong> informação orientada a um <strong>de</strong>terminado tema e que expressa a variação<br />
<strong>de</strong>sses dados ao longo do tempo, po<strong>de</strong>ndo esses dados ser usados para fins <strong>de</strong> apoio a <strong>de</strong>cisões<br />
[Inmon1996].<br />
Esta separação entre a base <strong>de</strong> dados operacional e a data warehouse promove a eficiência e<br />
<strong>de</strong>sempenho <strong>de</strong> cada um dos sistemas, tendo em conta os diferentes fins a que se <strong>de</strong>stina. A principal<br />
função das bases <strong>de</strong> dados operacionais é a realização <strong>de</strong> transacções online e processamento <strong>de</strong><br />
interrogações (queries), sendo esse conjunto <strong>de</strong> operações conhecido como processamento <strong>de</strong><br />
transacções online (online transaction processing - OLTP). Em oposição, as data warehouses têm por<br />
objectivo servir <strong>de</strong> suporte à análise <strong>de</strong> dados e tomada <strong>de</strong> <strong>de</strong>cisões, pelo que sobre elas são realizados<br />
outros tipos <strong>de</strong> operações. Normalmente, tratam-se <strong>de</strong> operações que manipulam gran<strong>de</strong>s quantida<strong>de</strong>s<br />
<strong>de</strong> dados históricos, permitem a realização <strong>de</strong> sumarizações e agregações e a gestão <strong>de</strong> informação em<br />
diferentes níveis <strong>de</strong> granularida<strong>de</strong>. A este tipo <strong>de</strong> operações dá-se o nome <strong>de</strong> processamento analítco<br />
online (online analytical processing - OLAP).<br />
De uma forma genérica, uma data warehouse é composta por uma tabela <strong>de</strong> factos, on<strong>de</strong> se encontram<br />
os dados que po<strong>de</strong>m ser objecto <strong>de</strong> análise, e tabelas <strong>de</strong> dimensões, que armazenam os dados sobre as<br />
perspectivas segundo as quais os factos po<strong>de</strong>m ser analisados. Tanto as data warehouses como as<br />
operações OLAP são baseadas no mo<strong>de</strong>lo multidimensional, em que os dados são visualizados sob a<br />
forma <strong>de</strong> um cubo. Um cubo é <strong>de</strong>finido por um conjunto <strong>de</strong> dimensões e <strong>de</strong> factos. De uma forma<br />
genérica, as dimensões são as perspectivas ou entida<strong>de</strong>s em relação às quais os factos se referem.<br />
Por exemplo, uma empresa po<strong>de</strong> manter uma data warehouse <strong>de</strong> vendas como forma <strong>de</strong> manter<br />
registos sobre as suas vendas no que se refere aos itens vendidos, à filial em que foram vendidos e à<br />
data <strong>de</strong> venda. Cada dimensão po<strong>de</strong> estar associada a uma tabela que pormenoriza a sua <strong>de</strong>scrição. No<br />
13
exemplo anterior, a tabela <strong>de</strong> dimensão para os itens vendidos po<strong>de</strong> conter os atributos nome, categoria<br />
e marca. Quanto aos factos, estes são medidas numéricas correspon<strong>de</strong>ntes ao principal objectivo da<br />
data warehouse. Ainda no exemplo anterior, o número <strong>de</strong> unida<strong>de</strong>s vendidas ou o volume total <strong>de</strong><br />
vendas em dinheiro são factos possíveis para uma data warehouse <strong>de</strong> vendas.<br />
Ao contrário do sólido geométrico com o nome correspon<strong>de</strong>nte, em OLAP os cubos não são<br />
necessariamente tridimensionais mas sim n-dimensionais. A melhor forma <strong>de</strong> esclarecer este conceito<br />
passa por exemplificar o mesmo. Para tal, consi<strong>de</strong>re-se a tabela abaixo, que representa informação<br />
sobre as vendas <strong>de</strong> uma <strong>de</strong>terminada organização apresentada em função do tempo (Tempo) e do tipo<br />
<strong>de</strong> item vendido (Item).<br />
Tabela 1 <strong>–</strong> Volume <strong>de</strong> vendas em função do tempo e do tipo <strong>de</strong> item para a cida<strong>de</strong> <strong>de</strong> Vancouver [Han2001a]<br />
Tempo<br />
(trimestre)<br />
Vendas para todas as localizações em Vancouver<br />
Item (tipo)<br />
Entretenimento Computador Telefone Segurança<br />
Q1 605k 825k 14k 400k<br />
Q2 680k 952k 31k 512k<br />
Q3 812k 1023k 30k 501k<br />
Q4 927k 1038k 38k 580k<br />
No caso <strong>de</strong> preten<strong>de</strong>rmos visualizar a informação relativa às vendas não apenas em função do tempo e<br />
dos itens vendidos mas também em função da Localização em que a venda foi feita, seria necessário<br />
acrescentar à tabela acima uma terceira dimensão, obtendo-se assim uma série <strong>de</strong> tabelas diferentes 1 .<br />
Tabela 2 <strong>–</strong> Volume <strong>de</strong> vendas em função do tempo, tipo <strong>de</strong> item e localização [Han2001a]<br />
Tempo<br />
(trimestre)<br />
Entretenimento<br />
Localização = Vancouver<br />
Item<br />
Computador Telefone Segurança<br />
Q1 605k 825k 14k 400k<br />
Q2 680k 952k 31k 512k<br />
Q3 812k 1023k 30k 501k<br />
Q4 927k 1038k 38k 580k<br />
Tempo<br />
(trimestre)<br />
Entretenimento<br />
Localização = Montréal<br />
Item<br />
Computador Telefone Segurança<br />
Q1 818k 746k 43k 591k<br />
Q2 894k 769k 52k 682k<br />
Q3 940k 795k 58k 728k<br />
Q4 978k 864k 59k 784k<br />
1 Estas tabelas po<strong>de</strong>m ser representadas numa só pivot tabela, tal como se <strong>de</strong>screve mais adiante.<br />
14
Tempo<br />
(trimestre)<br />
Entretenimento<br />
Localização = New York<br />
Item<br />
Computador Telefone Segurança<br />
Q1 1087k 968k 38k 872k<br />
Q2 1130k 1024k 41k 925k<br />
Q3 1034k 1048k 45k 1002k<br />
Q4 1142k 1091k 54k 984k<br />
Tempo<br />
(trimestre)<br />
Entretenimento<br />
Localização = Chicago<br />
Item<br />
Computador Telefone Segurança<br />
Q1 854k 882k 89k 623k<br />
Q2 943k 890k 64k 698k<br />
Q3 1032k 924k 59k 789k<br />
Q4 1129k 992k 63k 870k<br />
As tabelas acima equivalem conceptualmente ao cubo 3D da figura abaixo.<br />
Figura 1 <strong>–</strong> Representação sob a forma <strong>de</strong> cubo 3D da tabela 2 [Han2001a]<br />
Supondo que se preten<strong>de</strong>sse adicionar outra dimensão, <strong>de</strong>signada como Fornecedor, à informação da<br />
tabela 1, obter-se-ia um cubo 4D, o que não é trivial <strong>de</strong> representar ou visualizar. Porém, po<strong>de</strong>mos<br />
consi<strong>de</strong>rar um cubo 4D como uma série <strong>de</strong> cubos 3D para cada uma das combinações possíveis das<br />
quatro dimensões três a três. Desta forma, qualquer informação n-dimensional po<strong>de</strong> ser representada<br />
sob a forma <strong>de</strong> uma série <strong>de</strong> cubos (n-1)-dimensionais. No fundo, o termo cubo é apenas uma metáfora<br />
para representar o carácter multidimensional dos dados.<br />
15
Dado um conjunto <strong>de</strong> dimensões, é possível construir uma malha <strong>de</strong> cubói<strong>de</strong>s em que cada um <strong>de</strong>les<br />
mostra os dados em diferentes níveis <strong>de</strong> sumarização ou agregação, isto, agrupados segundo diferentes<br />
subconjuntos das dimensões. Um cubo como o da figura 1 é normalmente <strong>de</strong>signado <strong>de</strong> cubói<strong>de</strong> base,<br />
enquanto o cubói<strong>de</strong> 0D, que apresenta o mais alto grau <strong>de</strong> sumarização possível, é o cubo ápice. Ao<br />
conjunto da malha <strong>de</strong> cubói<strong>de</strong>s dá-se o nome <strong>de</strong> cubo <strong>de</strong> dados (data cube).<br />
Figura 2 <strong>–</strong> Malha <strong>de</strong> cubói<strong>de</strong>s para um cubo 4D [Han2001a]<br />
O mo<strong>de</strong>lo multidimensional <strong>de</strong> dados po<strong>de</strong> ser implementado segundo um esquema em estrela, em floco<br />
<strong>de</strong> neve ou em constelação <strong>de</strong> factos. O esquema em estrela é o esquema mais usado para representar<br />
data warehouses, sendo composto por uma tabela central <strong>de</strong> factos e várias tabelas <strong>de</strong> dimensão<br />
ligadas à tabela central. O esquema em floco <strong>de</strong> neve é uma variante do esquema em estrela que, ao<br />
propor a normalização das tabelas relativas às dimensões, elimina alguns problemas <strong>de</strong> redundância<br />
<strong>de</strong>vidos ao facto <strong>de</strong> cada dimensão correspon<strong>de</strong>r a uma única tabela no esquema em estrela. A nível<br />
arquitectural, as data warehouses po<strong>de</strong>m ser implementadas sobre sistemas <strong>de</strong> gestão <strong>de</strong> bases <strong>de</strong><br />
dados relacionais, <strong>de</strong>signados como servidores relacionais (servidores ROLAP) e que suportam métodos<br />
especiais que lhes permitem implementar o mo<strong>de</strong>lo multidimensional e as operações sobre ele. Outra<br />
arquitectura possível para as data warehouses assenta em servidores multidimensionais (servidores<br />
MOLAP), que recorrem a estruturas <strong>de</strong> dados apropriadas para implementar o mo<strong>de</strong>lo multidimensional<br />
e as operações necessárias.<br />
Para tirar partido da flexibilida<strong>de</strong> proporcionada pelo mo<strong>de</strong>lo multidimensional, existem várias operações<br />
que po<strong>de</strong>m ser realizadas sobre o cubo e permitem obter diferentes vistas dos dados. Para a <strong>de</strong>scrição<br />
das operações mais comuns, consi<strong>de</strong>re-se o mo<strong>de</strong>lo multidimensional representado na figura 3.<br />
16
Figura 3 <strong>–</strong> Exemplo <strong>de</strong> um mo<strong>de</strong>lo multidimensional [Chanduri1997]<br />
A operação <strong>de</strong> roll-up permite realizar agregações ao subir na hierarquia <strong>de</strong> uma dimensão. Tomando a<br />
dimensão Cida<strong>de</strong> <strong>de</strong>finida na figura 3, um exemplo <strong>de</strong> uma operação <strong>de</strong> roll-up será aquela que agrega<br />
os dados subindo na hierarquia do nível cida<strong>de</strong> para o nível país. Este tipo <strong>de</strong> operação po<strong>de</strong> também<br />
ser conseguida através da remoção <strong>de</strong> dimensões, que na prática tem o mesmo efeito <strong>de</strong> agregação dos<br />
dados em torno das dimensões que não são removidas.<br />
A operação <strong>de</strong> drill-down é inversa à operação <strong>de</strong> roll-up, permitindo passar <strong>de</strong> um nível <strong>de</strong> menor<br />
<strong>de</strong>talhe para um nível <strong>de</strong> maior <strong>de</strong>talhe.Tomando a dimensão Produto na figura 3, um exemplo <strong>de</strong> uma<br />
operação <strong>de</strong> drill-down seria aquela em que se passasse do nível <strong>de</strong> trimestre para o nível <strong>de</strong> mês. À<br />
semelhança do que se verifica para a operação <strong>de</strong> roll-up, a operação <strong>de</strong> drill-down po<strong>de</strong> ser conseguida<br />
adicionando dimensões ao cubo, no sentido do maior <strong>de</strong>talhe permitido pela operação.<br />
As operações <strong>de</strong> slice e dice correspon<strong>de</strong>m a acções <strong>de</strong> selecção por parte do utilizador. Enquanto a<br />
primeira correspon<strong>de</strong> à selecção <strong>de</strong> dados do cubo tendo em conta apenas uma dimensão, a segunda<br />
correspon<strong>de</strong> à selecção <strong>de</strong> dados por mais que uma dimensão. O resultado <strong>de</strong> qualquer uma das<br />
operações é o subcubo correspon<strong>de</strong>nte aos critérios enumerados. No exemplo dado na figura 3, é<br />
possível fazer slice e dice aos dados <strong>de</strong> modo a obter uma tabela que apenas contém os valores<br />
referentes à dimensão cida<strong>de</strong> e ao dia <strong>de</strong> venda <strong>de</strong> um <strong>de</strong>terminado produto.<br />
A operação <strong>de</strong> pivoting é uma técnica <strong>de</strong> visualização em que os eixos do cubo são rodados <strong>de</strong> forma a<br />
possibilitar outra perspectiva dos dados. O significado <strong>de</strong>sta operação é melhor entendido se se<br />
visualizar o mo<strong>de</strong>lo multidimensional da figura 3 representado numa folha <strong>de</strong> cálculo em que cada linha<br />
correspon<strong>de</strong> a uma venda, representando cada coluna uma dimensão e a última coluna o valor da venda<br />
[Chanduri1997]. O valor contido em cada célula representa o valor agregado <strong>de</strong> uma <strong>de</strong>terminada<br />
medida (neste caso, o valor <strong>de</strong> vendas) quando a primeira dimensão tem o valor x e a segunda<br />
dimensão tem o valor y. Seguindo o exemplo da figura 3 e assumindo que consi<strong>de</strong>ramos apenas as<br />
dimensões cida<strong>de</strong> e ano, então o eixo x representa todos os valores possíveis <strong>de</strong> cida<strong>de</strong> e o eixo y<br />
representa todos os valores possíveis <strong>de</strong> ano. Consequentemente, o ponto (x, y) representa o valor<br />
agregado <strong>de</strong> vendas para a cida<strong>de</strong> x no ano y. A operação <strong>de</strong> pivoting permite trocar os eixos x e y, o<br />
17
que faria com que cada ponto (x, y) passasse a representar o valor agregado <strong>de</strong> vendas para o ano x na<br />
cida<strong>de</strong> y.<br />
Além das mencionadas acima, existem outras operações OLAP oferecidas em sistemas comerciais, tais<br />
como o drill-through ou o drill-cross, que resultam da combinação <strong>de</strong> algumas das operações anteriores.<br />
2.2 O operador DATA CUBE<br />
Os utilizadores típicos <strong>de</strong> sistemas <strong>de</strong> apoio à <strong>de</strong>cisão estão mais interessados em extrair informação<br />
dos dados do que propriamente em visualizá-los, o que faz com que as interrogações que realizam<br />
exijam agregação dos dados, na maior parte dos casos sobre várias dimensões. O uso das funções <strong>de</strong><br />
agregação existentes no SQL (group-by e union) traz alguns problemas que serviram <strong>de</strong> motivação para<br />
a concepção do operador DATA CUBE, <strong>de</strong>stacando-se <strong>de</strong>sses problemas o cálculo <strong>de</strong> totais para<br />
operações <strong>de</strong> roll-up e <strong>de</strong> subtotais para operações <strong>de</strong> drill-down. A apresentação <strong>de</strong> resultados sob a<br />
forma <strong>de</strong> cross-tables, que são tabelas que expressam a relação entre os valores apresentados nas<br />
linhas e os valores apresentados nas colunas, também não é facilitada recorrendo às funções <strong>de</strong><br />
agregação nativas <strong>de</strong> SQL, uma vez que estas tabelas mostram o resultado <strong>de</strong> várias operações, como<br />
o total, o total das colunas e o total das linhas [Gray1997]. A tabela 3 mostra uma organização típica dos<br />
dados numa aplicação OLAP, em que os agregados são cada vez mais finos e em cada nível é gerado<br />
um subtotal.<br />
Tabela 3 <strong>–</strong> Roll-up das vendas por mo<strong>de</strong>lo, ano e cor adaptado <strong>de</strong> [Gray1997]<br />
Marca Ano Cor<br />
Vendas<br />
por mo<strong>de</strong>lo<br />
por ano por cor<br />
Chevy 1994 Preto 50<br />
Branco 40<br />
1995 Preto 85<br />
Branco 115<br />
Vendas<br />
por mo<strong>de</strong>lo<br />
por ano<br />
90<br />
Vendas<br />
por<br />
mo<strong>de</strong>lo<br />
Porém, a representação <strong>de</strong>sta tabela não é relacional visto que existem células vazias, inviabilizando<br />
assim a hipótese <strong>de</strong> funcionarem como i<strong>de</strong>ntificadores unívocos (chaves). Para obviar este problema,<br />
Chris Date recomendou a criação <strong>de</strong> 2 n colunas <strong>de</strong> agregação para um roll-up <strong>de</strong> n elementos<br />
[Gray1997], obtendo-se assim a tabela 4.<br />
200<br />
290<br />
18
Tabela 4 - Roll-up das vendas por mo<strong>de</strong>lo, ano e cor como sugerido por Chris Date, adaptado <strong>de</strong> [Gray1997]<br />
Mo<strong>de</strong>lo Ano Cor Unida<strong>de</strong>s<br />
Chevy 1994 Preto 50<br />
Chevy 1994 Branco 40<br />
Chevy 1994 ALL 90<br />
Chevy 1995 Preto 85<br />
Chevy 1995 Branco 115<br />
Chevy 1995 ALL 200<br />
Chevy ALL ALL 290<br />
Esta alternativa, apesar <strong>de</strong> elegante, aumenta significativamente o número <strong>de</strong> células a calcular quando<br />
o número <strong>de</strong> dimensões aumenta ligeiramente. Para evitar o crescimento exagerado das tabelas <strong>de</strong>vido<br />
à adição das novas colunas, os autores propuseram a re<strong>de</strong>finição dos valores das colunas, introduzindo<br />
o valor ALL. Cada valor ALL representa um conjunto <strong>de</strong> dados sobre o qual já foi computado o valor da<br />
agregação. A tabela 5 mostra o resultado da aplicação <strong>de</strong>sta representação.<br />
Tabela 5 - Resultado após computada a agregação, adaptado <strong>de</strong> [Gray1997]<br />
Marca Ano Cor Vendas Vendas<br />
Por mo<strong>de</strong>lo<br />
Por ano<br />
Vendas<br />
Por<br />
mo<strong>de</strong>lo<br />
Chevy 1994 Preto 50 90 290<br />
Chevy 1994 Branco 40 90 290<br />
Chevy 1995 Preto 85 200 290<br />
Chevy 1995 Branco 115 200 290<br />
Desta forma, a tabela representa uma relação e é possível obtê-la recorrendo a SQL standard,<br />
efectuando tantas uniões quantas as dimensões a serem consi<strong>de</strong>radas. Porém, como a operação <strong>de</strong> roll-<br />
up é simétrica, a tabela anterior necessita <strong>de</strong> ser acrescentada com a tabela 6 para que passe a<br />
representar um cubo.<br />
Tabela 6 - Linhas a acrescentar à tabela 3 adaptado <strong>de</strong> [Gray1997]<br />
Mo<strong>de</strong>lo Ano Cor Unida<strong>de</strong>s<br />
Chevy ALL Preto 135<br />
Chevy ALL Branco 135<br />
As linhas constantes da tabela 6 po<strong>de</strong>m ser obtidas adicionando uma união à instrução <strong>de</strong> SQL a partir<br />
da qual se obteve a tabela 5. O resultado <strong>de</strong>sta junção permite que a operação <strong>de</strong> roll-up seja simétrica e<br />
gera a tabela 7, a que se dá o nome <strong>de</strong> cross tab.<br />
19
Tabela 7 - Cross table para as vendas da marca Chevy adaptado <strong>de</strong> [Gray1997]<br />
Chevy 1994 1995 Total (ALL)<br />
Chevy ALL Preto 135<br />
Chevy ALL Branco 155<br />
Total (ALL) 90 200 290<br />
Esta pequena <strong>de</strong>monstração é suficiente para mostrar que, apesar do uso <strong>de</strong> group-by e union resolver o<br />
problema <strong>de</strong> calcular os agregados, a forma como isso é conseguido não é eficiente em termos <strong>de</strong><br />
tempo e gera representações <strong>de</strong> díficil análise. Com efeito, exprimir histogramas, roll-ups, drill-downs e<br />
cross tables recorrendo a SQL convencional não é imediato e trivial: uma cross table 6D requer a<br />
realização da operação union <strong>de</strong> 64 formas diferentes para 64 group-bys diferentes e continua a não ser<br />
realmente um objecto relacional [Gray1997].<br />
Em 1996, Gray et al propuseram o operador DATA CUBE ou, mais simplemente, CUBE, capaz <strong>de</strong><br />
computar agregados sobre todas as combinações possíveis <strong>de</strong> atributos para um conjunto <strong>de</strong><br />
dimensões. Basicamente, o operador CUBE é uma generalização n-dimensional das funções <strong>de</strong><br />
agregação básicas <strong>de</strong> SQL, tal como mostra a figura 4 [Gray1997].<br />
Figura 4 - Operador CUBE para cubos 0D, 1D, 2D e 3D [Gray1997]<br />
20
O cubo 0D (em cima à esquerda na figura 4) refere-se ao agregado vazio e correspon<strong>de</strong> à soma total <strong>de</strong><br />
todos os valores. Graficamente, o cubo 1D (em cima no centro da figura 4) tem o aspecto <strong>de</strong> uma linha e<br />
um ponto, na medida em que contém todos os valores agregados por um atributo e o resultado da soma<br />
<strong>de</strong> todos esses valores; na figura 2, correspon<strong>de</strong> ao agregado segundo o atributo cor. Por sua vez, o<br />
cubo 2D (em cima à direita na figura 4) correspon<strong>de</strong> a um plano, duas linhas e um ponto, ou seja, a uma<br />
cross-table com duas colunas e respectivos totais por linha e por coluna. Tal como mostra a figura 4, faz-<br />
se a agregação segundo dois atributos, que são marca e cor. Por fim, um cubo 3D (em baixo na figura 4)<br />
equivale à intersecção <strong>de</strong> três cross tables, correspon<strong>de</strong>ndo cada uma <strong>de</strong>las à agregação por diferentes<br />
grupos <strong>de</strong> atributos.<br />
Este novo operador surgiu como forma <strong>de</strong> ultrapassar as limitações <strong>de</strong>monstradas pelo uso <strong>de</strong> SQL. O<br />
trabalho apresentado foi posteriormente consi<strong>de</strong>rado tão relevante que foi mesmo realizada uma<br />
implementação <strong>de</strong>sse operador, com algumas alterações, em SQL, tal como referido em [Zhao1997].<br />
2.3 Selecção <strong>de</strong> agregados para pré-computação<br />
Tipicamente, os sistemas <strong>de</strong> apoio à <strong>de</strong>cisão <strong>de</strong>vem ser capazes <strong>de</strong> lidar com interrogações complexas<br />
sobre bases <strong>de</strong> dados <strong>de</strong> gran<strong>de</strong> dimensão e <strong>de</strong>volver respostas em tempos curtos, o que faz com que a<br />
optimização <strong>de</strong> interrogações seja fundamental. Tendo em conta que, neste contexto, os dados<br />
normalmente são vistos sob a forma do mo<strong>de</strong>lo multidimensional, uma das técnicas mais usadas neste<br />
sentido é a pré-computação <strong>de</strong> alguns agregados por forma a evitar a repetição <strong>de</strong>ste cálculo. Este<br />
problema da eficiência no cálculo <strong>de</strong> cubos foi estudado por Harinarayan et al, que propuseram uma<br />
plataforma para escolher quais os agregados que <strong>de</strong>vem ser calculados previamente [Harinarayan1996].<br />
Num cubo, existem várias células cujos valores são obtidos a partir <strong>de</strong> outras células. Assumindo que<br />
cada célula é representada por uma lista <strong>de</strong> valores relativos a cada uma das dimensões que a<br />
compõem, qualquer célula que tenha o valor ALL como um dos seus componentes <strong>de</strong>pen<strong>de</strong> <strong>de</strong> outra<br />
célula. Qualquer célula cuja composição não inclua o valor ALL po<strong>de</strong> ser obtida a partir da tabela <strong>de</strong><br />
dados. No seu trabalho, Harinarayan et al utilizaram uma base <strong>de</strong> dados com três atributos: peça (P),<br />
fornecedor (S) e cliente (C). Assim sendo, existem 2 3 conjugações possíveis <strong>de</strong>sses atributos: (peça,<br />
fornecedor, cliente), (peça, cliente), (peça, fornecedor), (fornecedor, cliente), (peça), (fornecedor),<br />
(cliente) e ( ). A última conjugação expressa o caso em que não são especificados atributos, o que<br />
significa que, num cubo com n dimensões, existem 2 n possíveis operações <strong>de</strong> agregação. A<br />
representação em malha na figura 5 mostra as relações entre as várias conjugações possíveis <strong>de</strong><br />
atributos.<br />
21
Figura 5 - Malha <strong>de</strong> combinações possíveis para 3 atributos [Harinarayan1996]<br />
Consi<strong>de</strong>rando duas interrogações Q1 e Q2, diz-se que Q1 <strong>de</strong>pen<strong>de</strong> <strong>de</strong> Q2 se Q1 po<strong>de</strong> ser respondida<br />
usando apenas os resultados <strong>de</strong> Q2. Tomando a figura 5, a interrogação (peça) po<strong>de</strong> ser respondida<br />
usando os resultados da interrogação (peça, cliente); logo, a interrogação (peça) <strong>de</strong>pen<strong>de</strong> da<br />
interrogação (peça, cliente).<br />
Este trabalho introduziu também o mo<strong>de</strong>lo <strong>de</strong> custo linear (linear cost mo<strong>de</strong>l) para exprimir o custo <strong>de</strong><br />
uma <strong>de</strong>terminada interrogação. Segundo este mo<strong>de</strong>lo, o tempo necessário para respon<strong>de</strong>r a uma<br />
interrogação Q correspon<strong>de</strong> ao número <strong>de</strong> linhas existentes na tabela <strong>de</strong> dados e que são necessárias<br />
para respon<strong>de</strong>r à interrogação QA, previamente respondida e da qual a interrogação Q <strong>de</strong>pen<strong>de</strong>.<br />
2.4 Computação <strong>de</strong> agregados multidimensionais<br />
Tal como foi referido, a tarefa <strong>de</strong> computar um cubo correspon<strong>de</strong>, basicamente, a pré-computar e<br />
armazenar agregações <strong>de</strong> dados multidimensionais <strong>de</strong> maneira a que seja possível analisar<br />
imediatamente esses dados. Naturalmente, esta é uma tarefa que consome bastantes recursos a nível<br />
<strong>de</strong> tempo e espaço. Logo, o <strong>de</strong>sempenho é uma questão fulcral no que se refere à computação e<br />
representação do cubo, tendo sido <strong>de</strong>senvolvidos vários algoritmos para esta tarefa.<br />
Segundo [Gray1997], as funções <strong>de</strong> agregação po<strong>de</strong>m ser classificados em três categorias:<br />
Funções distributivas <strong>–</strong> a função F( ) é consi<strong>de</strong>rada distributiva se existir uma função G( ) tal que<br />
F({Xi,j}) = G({F({Xi,j | i = 1, ..., I}) |j = 1, ..., J}); como exemplos, temos as funções COUNT( ),<br />
MIN( ), MAX( ) e SUM( ).<br />
Funções algébricas <strong>–</strong> a função F( ) é consi<strong>de</strong>rada algébrica se existir um tuplo <strong>de</strong> or<strong>de</strong>m M <strong>de</strong><br />
valores <strong>de</strong> uma função G( ) e uma função H( ) tal que F({Xi,j}) = H({G({Xi,j | i = 1, ..., I}) | j = 1, ...,<br />
J}); como exemplos, temos a função AVG().<br />
Funções holísticas <strong>–</strong> uma função F( ) é consi<strong>de</strong>rada holística se não existir uma constante M tal<br />
que caracterize a computação F({Xi,j | i = 1, ..., I}); como exemplo, temos a mediana ou a moda.<br />
No que se refere às funções holísticas, a forma mais eficiente <strong>de</strong> computar agregados <strong>de</strong>ste tipo <strong>de</strong><br />
funções é o recurso ao algoritmo 2 N [Gray1997]. Este algoritmo começa por reservar um apontador<br />
22
Para isso, foram estudados dois métodos básicos para computação <strong>de</strong> um único agregado: um <strong>de</strong>les é<br />
baseado em or<strong>de</strong>namento (PipeSort) e outro é baseado em dispersão (PipeHash) [Agrawal1996]. Estes<br />
métodos po<strong>de</strong>m ser aplicados à computação <strong>de</strong> múltiplos agregados recorrendo às seguintes<br />
optimizações:<br />
Pais mais pequenos (smallest-parents) <strong>–</strong> consiste em computar um agregado a partir <strong>de</strong> outros<br />
<strong>de</strong> menor dimensão já computados.<br />
Resultados em cache (cache-results) <strong>–</strong> consiste em manter em memória os resultados <strong>de</strong> um<br />
agregado a partir do qual seja possível calcular outros, por forma a evitar as operações <strong>de</strong><br />
entrada e saída.<br />
Amortização <strong>de</strong> varrimentos (amortize-scans) <strong>–</strong> trata-se <strong>de</strong> amortizar o número <strong>de</strong> operações <strong>de</strong><br />
leitura do disco ao computar o maior número <strong>de</strong> agregados que for possível manter em memória.<br />
Partilha da or<strong>de</strong>nação (share-sorts) <strong>–</strong> apenas se aplica a algoritmos baseados em or<strong>de</strong>nação e<br />
aposta na partilha dos custos associados à or<strong>de</strong>nação por vários agregados.<br />
Partilha <strong>de</strong> partições (share-partitions) <strong>–</strong> apenas se aplica a algoritmos que utilizem dispersão e<br />
refere-se à partição da tabela <strong>de</strong> dispersão, caso seja <strong>de</strong>masiado gran<strong>de</strong> para os recursos <strong>de</strong><br />
memória disponíveis, e a efectuar a agregação apenas para cada uma das partições.<br />
Tanto PipeSort como PipeHash computam vários agregados segundo uma lógica sequencial, sendo<br />
cada fio <strong>de</strong> computação constituído por agregados que po<strong>de</strong>m ser computados pelo mesmo varrimento<br />
dos dados <strong>de</strong> entrada. De forma a estabelecer quais os agregados que po<strong>de</strong>m ser computados a partir<br />
<strong>de</strong> outros e qual a sequência pela qual os atributos <strong>de</strong>vem ser tratados, foi utilizado o conceito <strong>de</strong> malha<br />
<strong>de</strong> procura apresentado em [Harinarayan1996].<br />
Basicamente, uma malha <strong>de</strong> procura é um grafo em que cada nó representa um agregado do cubo.<br />
Quando um nó i está ligado a um nó j, isso significa que o agregado j po<strong>de</strong> ser gerado a partir do<br />
agregado i e que j tem exactamente um atributo a menos que i [Agrawal1996]. A figura 7 apresenta um<br />
exemplo <strong>de</strong> uma malha <strong>de</strong> procura para quatro atributos (A, B, C e D), em que cada nível k reúne os<br />
agregados que contêm exactamente k atributos.<br />
Figura 7 - Exemplo <strong>de</strong> uma malha <strong>de</strong> procura [Agrawal1996]<br />
24
Por exemplo, no nível 2 da malha todos os agregados contêm exactamente dois atributos. A única<br />
excepção a esta regra é o nível 0, que apenas contém um agregado vazio e é representado pelo termo<br />
ALL. Cada arco da malha está etiquetado com dois custos: o custo S(eij) correspon<strong>de</strong> ao custo <strong>de</strong><br />
computar j a partir <strong>de</strong> i quando i ainda não está or<strong>de</strong>nado, enquanto o custo A(eij) correspon<strong>de</strong> ao custo<br />
<strong>de</strong> computar j a partir <strong>de</strong> i quando i já está or<strong>de</strong>nado [Agrawal1996].<br />
2.4.1.1 PipeSort<br />
O algoritmo PipeSort parte da malha <strong>de</strong> procura com os respectivos custos associados e assume que se<br />
conhece uma estimativa do número <strong>de</strong> valores distintos associados a cada agregado. A malha é<br />
percorrida <strong>de</strong>s<strong>de</strong> o nível k = 0 até ao nível k = N - 1, sendo N o número total <strong>de</strong> atributos, com o objectivo<br />
<strong>de</strong> <strong>de</strong>terminar a melhor forma <strong>de</strong> computar o nível k a partir do nível k + 1. Para isso, é acrescentado ao<br />
nível k + 1 k cópias <strong>de</strong> cada agregado nesse nível e cada nó replicado é ligado ao mesmo conjunto <strong>de</strong><br />
nós a que está ligado o vértice original na malha [Agrawal1996]. A figura 8 mostra este procedimento,<br />
consi<strong>de</strong>rando que se trabalha sobre o nível 1 da malha apresentada na figura 7. As setas em traço cheio<br />
representam os arcos A( ), enquanto as setas a tracejado representam os arcos S( ), sendo o custo <strong>de</strong><br />
todos os arcos que saem <strong>de</strong> um nó indicados sob eles.<br />
Figura 8 - Parte da malha <strong>de</strong> procura transformada [Agrawal1996]<br />
Sabendo que o custo eij <strong>de</strong>s<strong>de</strong> o nó original i até ao nó j <strong>de</strong> nível k é A(eij) e que todos os nós replicados<br />
<strong>de</strong> i têm um custo <strong>de</strong> S(eij), é possível encontrar, para cada nó h no nível k, um vértice g no nível k + 1 a<br />
partir do qual h po<strong>de</strong> ser calculado. Como se po<strong>de</strong> ver na figura 20, o nó A fica ligado ao nó AB por um<br />
arco S( ) e o nó B está ligado a AB por um arco A( ). No nível k = 2, o agregado AB será computado pela<br />
or<strong>de</strong>m BA para que B possa ser obtido a partir <strong>de</strong>le sem necessida<strong>de</strong> <strong>de</strong> reor<strong>de</strong>nação e A seja obtido<br />
reor<strong>de</strong>nando BA. Da mesma forma, como o nó C está ligado ao nó AC por um arco A( ), o nó AC será<br />
computado pela or<strong>de</strong>m CA. Quanto ao nó BC, como não está ligado a nenhum agregado <strong>de</strong> nível 1, é<br />
indiferente a or<strong>de</strong>m pela qual é calculado.<br />
Figura 9 - Resultado obtido pelo algoritmo PipeSort para k = 1 [Agrawal1996]<br />
25
Seguidamente, é feita uma or<strong>de</strong>nação com base no sub-grafo gerado e é obtido um conjunto <strong>de</strong><br />
sequências <strong>de</strong> agregados a serem computadas em sequência (pipeline).<br />
Este algoritmo concilia as optimizações partilha da or<strong>de</strong>nação (share-sort), uma vez que os dados são<br />
or<strong>de</strong>nados numa <strong>de</strong>terminada or<strong>de</strong>m que permita computar todos os agregados que partilham um<br />
prefixo, e pais mais pequenos (smallest parents), uma vez que os agregados são sempre calculados a<br />
partir <strong>de</strong> outros agregados <strong>de</strong> menor dimensão já calculados. Além disso, emprega ainda as<br />
optimizações resultados em cache (cache-results) e amortização <strong>de</strong> varrimentos (amortize-scans) para<br />
reduzir o número <strong>de</strong> acessos ao disco, pois adopta uma política <strong>de</strong> cálculo em pipeline.<br />
2.4.1.2 PipeHash<br />
O algoritmo PipeSort trabalha igualmente sobre a malha <strong>de</strong> procura e começa por escolher, para cada<br />
agregado, o seu pre<strong>de</strong>cessor <strong>de</strong> menor dimensão, obtendo assim a árvore <strong>de</strong> custo mínimo. Porém, os<br />
recursos normalmente disponíveis continuam a não ser suficientes para computar todos os agregados<br />
<strong>de</strong>ssa árvore, pelo que é necessário <strong>de</strong>cidir quais serão computados em conjunto, quando reservar<br />
memória para diferentes tabelas <strong>de</strong> dispersão e que atributos serão usados para dividir os dados<br />
[Agrawal1996].<br />
O algoritmo começa por seleccionar para, cada agregado, o agregado-pai com menor dimensão total<br />
estimada. No final, obtém uma árvore <strong>de</strong> cobertura mínima (minimum spanning tree), em que cada nó<br />
representa um agregado e cada arco que une o nó A ao nó B indica que A é o menor pai <strong>de</strong> B. A figura<br />
abaixo apresenta a árvore <strong>de</strong> cobertura mínima para a malha <strong>de</strong> procura apresentada na figura 7.<br />
Figura 10 - Árvore <strong>de</strong> cobertura mínima para a malha <strong>de</strong> procura apresentada na figura 7 [Agrawal1996]<br />
Na maioria dos casos, a memória disponível não será suficiente para calcular todos os agregados da<br />
árvore, pelo que é necessário dividir a árvore assim obtida. A árvore é dividida <strong>de</strong> tal forma que cada<br />
uma das sub-árvores obtidas possa ser calculada com uma única passagem do agregado na raiz da<br />
árvore original. Este é um problema NP-completo, o que obriga a escolher uma aproximação à solução;<br />
26
neste caso, o critério consiste em escolher para efectuar a partição o atributo que permita obter a maior<br />
sub-árvore possível a partir da árvore <strong>de</strong> custo mínimo.<br />
Tomando a árvore <strong>de</strong> cobertura mínima da figura 10 e assumindo que não há espaço em memória para<br />
calcular todos os agregados nela representados, há que efectuar a partição da árvore. Quando A é<br />
escolhido como atributo pelo qual se vai efectuar a partição, obtém-se a sub-árvore à esquerda na figura<br />
22. Para computar esta árvore, calcula-se primeiro o agregado ABCD e a partir <strong>de</strong>ste ABC, ABD e ACD;<br />
ABCD e ABD são guardados em disco, calcula-se AD a partir <strong>de</strong> ACD e ACD e AD são guardados em<br />
disco; ABC é lido para a partir <strong>de</strong>le se calcular AB e AC, sendo ABC e AC guardados em disco; por fim,<br />
AB é lido para calcular A e AB e A são guardados em disco. Depois <strong>de</strong>sta sub-árvore ter sido calculada,<br />
é removida da árvore original e são calculadas cada uma das sub-árvores restantes, à direita na figura<br />
11.<br />
Figura 11 - Sub-árvores obtidas por partição da árvore da figura 10 segundo o atributo A [Agrawal1996]<br />
Este algoritmo emprega as optimizações resultados em cache (cache-results) e amortização <strong>de</strong><br />
varrimentos (amortize-scans), pois mantém em memória todos os agregados <strong>de</strong> uma sub-árvore até que<br />
os seus filhos tenham sido calculados, assim como a optimização partilha <strong>de</strong> partições (share-partition)<br />
ao conseguir calcular a partir da mesma partição todos os agregados que contêm o atributo pelo qual se<br />
fez a partição.<br />
2.4.2 Algoritmos baseados em partição<br />
Os dados provenientes do mundo real são frequentemente <strong>de</strong> natureza esparsa, o que justifica o estudo<br />
e <strong>de</strong>senvolvimento <strong>de</strong> técnicas orientadas para esse tipo <strong>de</strong> dados. Nestas condições, a representação<br />
por meio <strong>de</strong> arrays não é uma hipótese viável visto que não é comportável em termos <strong>de</strong> memória. Os<br />
algoritmos baseados na partição dos dados usam dois princípios a que se recorre frequentemente para<br />
realizar operações complexas sobre relações amplas: efectuar a partição das relações em fragmentos<br />
que possam ser armazenados em memória e efectuar a operação sobre cada um <strong>de</strong>sses fragmentos<br />
in<strong>de</strong>pen<strong>de</strong>ntemente. Existem dois algoritmos para computação <strong>de</strong> cubos a partir <strong>de</strong> dados esparsos:<br />
27
Partitioned-Cube e Memory-Cube [Ross1997]. O algoritmo Memory-Cube foi concebido para computar<br />
eficientemente os cubos cujas relações possam ser mantidas em memória, enquanto o algoritmo<br />
Partitioned-Cube basicamente efectua a partição da relação e recorre ao Memory-Cube para computar<br />
as partições assim obtidas.<br />
A estrutura do algoritmo Partitioned-Cube segue a própria estrutura recursiva dos cubos. O cubo é obtido<br />
fixando cada um dos valores possíveis para um atributo e calculando os tuplos <strong>de</strong>sse sub-cubo. Em<br />
seguida calculam-se todos os tuplos do cubo que têm como valor para esse atributo ALL. Desta forma,<br />
em vez <strong>de</strong> voltar a ler os dados para calcular o cubo ALL, apenas é necessário ler o cubói<strong>de</strong> <strong>de</strong><br />
granularida<strong>de</strong> mais fina, que po<strong>de</strong> ser bastante menor que a relação que representa e nunca é maior que<br />
essa relação [Ross1997]. O algoritmo divi<strong>de</strong> o cubo em n + 1 subcubos mais pequenos, o que faz com<br />
que esses subcubos possam ser calculados em memória recorrendo ao algoritmo Memory-Cube.<br />
Consi<strong>de</strong>rando uma relação que possui quatro atributos or<strong>de</strong>nados como (A, B, C, D), o algoritmo<br />
proce<strong>de</strong> à partição dos dados tomando os atributos por essa or<strong>de</strong>m e calcula os cubói<strong>de</strong>s respectivos<br />
sempre que o resultado <strong>de</strong> cada partição possa ser guardado em memória. Assim, a relação em causa<br />
começa por ser dividida pelo atributo A, sendo computados os tuplos possíveis para cada um dos<br />
cubói<strong>de</strong>s que contêm A como atributo. Seguidamente, a relação é dividida pelo atributo B, sendo<br />
projectado o atributo A, e o procedimento é repetido, o que faz com que sejam computados todos os<br />
tuplos dos cubói<strong>de</strong>s que contêm B. A partição continua enquanto não se verificar que os cubói<strong>de</strong>s<br />
restantes po<strong>de</strong>m ser calculados em memória, embora o algoritmo não especifique exactamente como<br />
realizar a divisão. A figura 12 mostra a or<strong>de</strong>m pela qual o algoritmo calcula os vários cubói<strong>de</strong>s sempre<br />
que o resultado da partição cabe em memória.<br />
Figura 12 - Ilustração da lógica do funcionamento do algoritmo Partitioned-Cube [Ross1997]<br />
O algoritmo Memory-Cube foi <strong>de</strong>senvolvido para o caso em que toda a relação em estudo po<strong>de</strong> ser<br />
mantida em memória. Apesar <strong>de</strong> ser um bloco constituinte do algoritmo Partitioned-Cube, po<strong>de</strong> funcionar<br />
<strong>de</strong> forma in<strong>de</strong>pen<strong>de</strong>nte uma vez que é capaz <strong>de</strong> computar um cubo por completo sem necessida<strong>de</strong> <strong>de</strong><br />
guardar resultados intermédios. Essa característica permite-lhe operar requerendo apenas alguma<br />
capacida<strong>de</strong> <strong>de</strong> armazenamento extra além da que é utilizada pela relação. Basicamente, usa o conceito<br />
28
<strong>de</strong> malha <strong>de</strong> procura proposto pelo algoritmo PipeSort, a partir da qual <strong>de</strong>termina quais os cubói<strong>de</strong>s que<br />
po<strong>de</strong>m ser obtidos a partir <strong>de</strong> outros no sentido <strong>de</strong> minimizar o número <strong>de</strong> caminhos que é necessário<br />
percorrer para cobrir todos os nós. Assim, para cada cubo o algoritmo toma um caminho e or<strong>de</strong>na a<br />
relação em memória tendo em conta a or<strong>de</strong>nação dos atributos no nó inicial. Seguidamente, os dados<br />
são percorridos, sendo os agregados acumulados à medida que o caminho percorre os vários níveis <strong>de</strong><br />
granularida<strong>de</strong>.<br />
Os resultados mostram que o algoritmo faz o número mínimo possível <strong>de</strong> or<strong>de</strong>nações e consegue tirar<br />
partido dos prefixos comuns <strong>de</strong> diferentes agregados <strong>de</strong> forma a optimizar o custo a nível <strong>de</strong><br />
processamento. Além disso, os únicos custos <strong>de</strong> entrada/saída inerentes são os <strong>de</strong> entrada <strong>de</strong> dados e<br />
saída dos resultados, o que faz com que a carga total <strong>de</strong>ste tipo <strong>de</strong> operações seja linear em relação ao<br />
número <strong>de</strong> atributos envolvidos, sempre que a relação possa estar em memória.<br />
2.4.3 Algoritmos baseados em arrays<br />
Nos sistemas do tipo MOLAP, os dados são armazenados em arrays, o que faz com que as técnicas do<br />
tipo or<strong>de</strong>nação e dispersão não sejam aplicáveis. O próprio facto <strong>de</strong> ser utilizado outro tipo <strong>de</strong> estrutura<br />
<strong>de</strong> dados faz com que seja necessário ter em conta uma série <strong>de</strong> factores relacionados com o<br />
carregamento e armazenamento eficientes <strong>de</strong> arrays <strong>de</strong> gran<strong>de</strong>s dimensões e muito esparsos.<br />
O algoritmo Multi-Way Array Cubing, proposto por Zhao et al segue os princípios do paradigma MOLAP<br />
na medida em que o seu objectivo é percorrer as células dos arrays <strong>de</strong> tal forma que não seja necessário<br />
repetir a operação para calcular cada um dos sub-agregados. Por questões <strong>de</strong> <strong>de</strong>sempenho, os arrays<br />
têm que ser armazenados divididos em arrays <strong>de</strong> menor dimensão, recorrendo-se a uma estratégia<br />
<strong>de</strong>signada <strong>de</strong> chunking [Zhao1997].<br />
DS fonte <strong>de</strong> dados<br />
c chunk<br />
chunkSize tamanho do chunk<br />
O {D 1,D 2,...,D n : |D 1|≤|D 2|≤...≤|D n|}<br />
T MMST para or<strong>de</strong>m O<br />
m número <strong>de</strong> elementos <strong>de</strong> O<br />
para cada c no nivel m do array<br />
carregar dados para c a partir <strong>de</strong> DS<br />
i n<br />
para cada D i<br />
para cada posição <strong>de</strong> c<br />
val valor da posição<br />
fazer<br />
nextLevel m-1<br />
para cada nó em nextLevel<br />
remover posição não utilizada em nó<br />
agregar valor no nó<br />
até<br />
nextLevel≥0<br />
i i-1<br />
Figura 13 <strong>–</strong> Pseudocódigo genérico do algoritmo Multi-Way<br />
29
A técnica tradicional <strong>de</strong> armazenar o array em função <strong>de</strong> uma coluna ou <strong>de</strong> uma linha po<strong>de</strong> não ser<br />
eficiente em muitas situações. Consi<strong>de</strong>re-se uma representação <strong>de</strong> um array bidimensional com as<br />
dimensões Loja e Data, em que os dados relativos a Loja estão nas linhas e os valores relativos a Data<br />
nas colunas. Ace<strong>de</strong>r ao array em or<strong>de</strong>m a Lojas é eficiente, na medida em que cada página em disco<br />
contém várias Lojas. Porém, ace<strong>de</strong>r ao array em or<strong>de</strong>m a Data é ineficiente, especialmente se a<br />
dimensão Loja for gran<strong>de</strong>; nesse caso, cada página em disco só vai conter os dados relativos a uma<br />
Data, sendo necessário carregar outra página para ace<strong>de</strong>r a dados para a Data seguinte. Esta<br />
organização cria uma assimetria entre as dimensões, favorecendo uma em <strong>de</strong>trimento <strong>de</strong> outras<br />
[Zhao1997]. O recurso à estratégia <strong>de</strong> chunking faz com que o tratamento seja equitativo para todas as<br />
dimensões. Enten<strong>de</strong>-se por chunking uma forma <strong>de</strong> dividir arrays n-dimensionais em vários arrays n-<br />
dimensionais mais pequenos (chunks), que são armazenados no disco como objectos distintos<br />
[Zhao1997].<br />
Porém, especialmente no que se refere a dados reais, é frequente que muitas das células do chunk<br />
estejam vazias, o que significa que não existem dados para essa combinação <strong>de</strong> coor<strong>de</strong>nadas. Um<br />
chunk é consi<strong>de</strong>rado <strong>de</strong>nso quando mais <strong>de</strong> 40% das células contêm um valor válido [Zhao1997].<br />
Quando esta situação não se verifica, diz-se que o chunk é esparso e é necessário aplicar-lhe uma<br />
técnica <strong>de</strong> compressão <strong>de</strong> tal forma que cada célula fica associada a um valor inteiro que indica o seu<br />
afastamento (offset) em relação ao início do chunk, evitando assim o armazenamento <strong>de</strong> células vazias.<br />
Desta forma, cada entrada válida passa a ser representada por um par (afastamento, valor).O recurso ao<br />
chunking assegura a eficiência a nível <strong>de</strong> carregamento e armazenamento dos valores das células do<br />
cubo, enquanto a eficiência a nível <strong>de</strong> computação dos agregados é assegurada pelo uso da or<strong>de</strong>m<br />
correcta no seu cálculo. Para isso, o algoritmo apresenta os conceitos <strong>de</strong> or<strong>de</strong>namento óptimo das<br />
dimensões (optimal dimension or<strong>de</strong>r) e árvore <strong>de</strong> cobertura mínima <strong>de</strong> memória (minimum memory<br />
spanning tree).<br />
Apesar <strong>de</strong> ser um algoritmo característico <strong>de</strong> aplicações do tipo MOLAP, po<strong>de</strong> ser usado por sistemas do<br />
tipo ROLAP, bastando para isso percorrer a tabela que contém os dados, carregá-la para um array,<br />
computar o resultado sobre esse array e transferir os resultados obtidos para as tabelas a<strong>de</strong>quadas.<br />
Esta adaptação justifica-se pelo elevado <strong>de</strong>sempenho que este algoritmo apresenta e pela boa gestão<br />
<strong>de</strong> memória que efectua, sendo ainda mais eficiente que os algoritmos <strong>de</strong>senhados para sistemas<br />
ROLAP.<br />
2.4.3.1 Computação <strong>de</strong> agregados<br />
Para compreen<strong>de</strong>r a mecânica do algoritmo, comecemos por computar um agregado a partir <strong>de</strong> um array<br />
simples sem recorrer a chunking, assumindo que se dispõe <strong>de</strong> um array tridimensional com dimensões<br />
A, B e C. Computar o agregado AB equivale a projectar C sobre o plano AB, o que logicamente<br />
correspon<strong>de</strong> a percorrer um plano através da dimensão C e realizar a agregação até que todo o array<br />
30
tenha sido percorrido. Se o array estivesse armazenado sob a forma <strong>de</strong> vários chunks, a computação <strong>de</strong><br />
AB seria feita não percorrendo um plano completo <strong>de</strong> dimensão |A||B|, em que |A| e |B| são<br />
respectivamente o tamanho da dimensão A e B, isso seria feito chunk a chunk. Supondo que a dimensão<br />
A num chunk tem tamanho AC e que a dimensão B num chunk tem tamanho BC e que o array é orientado<br />
<strong>de</strong> tal forma que a face AB do array está <strong>de</strong> frente para o leitor, o chunk po<strong>de</strong> ter início na parte superior<br />
esquerda do array e percorrer um plano <strong>de</strong> dimensão ACBC, agregando todos os valores <strong>de</strong> C no<br />
processo. Depois <strong>de</strong> percorrido este chunk na porção superior esquerda, o varrimento <strong>de</strong>ste plano<br />
continua através do chunk imediatamente atrás do que se encontra no topo superior esquerdo e termina<br />
apenas quando o plano foi todo percorrido <strong>de</strong>ntro do array. Neste ponto, a porção do agregado AB<br />
correspon<strong>de</strong>nte ao subplano superior esquerdo <strong>de</strong> dimensão ACBC já foi computada, pelo que este plano<br />
é guardado em disco como a primeira parte do agregado AB e prosseguir com o cálculo do subplano<br />
correspon<strong>de</strong>nte a outro chunk. Desta forma, cada chunk apenas é lido uma vez e no fim <strong>de</strong> serem<br />
percorridos todos os chunks o agregado AB encontrar-se-á em disco como uma colecção <strong>de</strong> planos <strong>de</strong><br />
tamanho ACBC. A memória usada por este processo é a suficiente para conter um chunk e o plano ACBC<br />
à medida que os chunks são varridos [Zhao1997].<br />
Porém, para computar um cubo é necessário computar mais que um agregado do mesmo. Num array<br />
com as dimensões ABC, consi<strong>de</strong>re-se agora que é necessário computar AB, BC, AC, A, B, C e o<br />
agregado total. Uma abordagem ingénua consistiria em computar todos estes agregados a patir do array<br />
inicial ABC. Porém, é muito mais eficiente calcular A a partir <strong>de</strong> AB do que calcular A a partir <strong>de</strong> ABC. Se<br />
se vir a computação do cubo como uma árvore em que ABC é a raiz, AB, BC e AC <strong>de</strong>scen<strong>de</strong>m <strong>de</strong> ABC,<br />
A e C <strong>de</strong>scen<strong>de</strong>m <strong>de</strong> AC e assim sucessivamente. Como as dimensões do array e o tamanho <strong>de</strong> cada<br />
um dos chunks são conhecidos, é possível <strong>de</strong>terminar exactamente o tamanho do array correspon<strong>de</strong>nte<br />
a cada nó da árvore e estimar o espaço necessário para o seu cálculo. Isto significa que é possível<br />
<strong>de</strong>finir a árvore mínima <strong>de</strong> cobertura (minimum spanning tree) em que o pre<strong>de</strong>cessor <strong>de</strong> cada nó n é o<br />
nó n’ <strong>de</strong> menor tamanho a partir do qual n po<strong>de</strong> ser computado. O funcionamento do algoritmo apoia-se<br />
na construção da árvore mínima <strong>de</strong> cobertura para os agregados do cubo que se preten<strong>de</strong> computar.<br />
Cada agregado Di1, Di2, ..., Dik+1 é calculado a partir do pre<strong>de</strong>cessor Di1, Di2, ..., Dik+1 com tamanho<br />
mínimo; cada chunk <strong>de</strong> Di1, Di2, ..., Dik+1 é lido segundo a dimensão Dik+1 e agregado para um chunk <strong>de</strong><br />
Di1, Di2, ..., Dik. Quando o chunk <strong>de</strong> Di1, Di2, ..., Dik estiver completo, é guardado em disco e a memória é<br />
libertada para o chunk seguinte <strong>de</strong> Di1, Di2, ..., Dik [Zhao1997].<br />
O recurso ao chunking assegura a eficiência a nível <strong>de</strong> carregamento e armazenamento dos valores das<br />
células do cubo, enquanto a eficiência a nível <strong>de</strong> <strong>de</strong>sempenho é assegurada pelo uso da or<strong>de</strong>m correcta<br />
no cálculo dos agregados. A or<strong>de</strong>m das dimensões num chunk po<strong>de</strong> ser representada como O = (Dj1, Dj2,<br />
... , Djn), assumindo que existem n dimensões D1, D2, ..., Dn. Diferentes or<strong>de</strong>namentos <strong>de</strong> dimensões<br />
implicam diferentes or<strong>de</strong>ns <strong>de</strong> leitura dos chunks e <strong>de</strong>terminam a quantida<strong>de</strong> <strong>de</strong> memória que é<br />
necessária para efectuar a computação. Para mostrar a importância da or<strong>de</strong>m pela qual são tomadas as<br />
dimensões, consi<strong>de</strong>re-se um array <strong>de</strong> dados 3D com três dimensões (A, B e C), dividido em 64 chunks<br />
31
como mostra a figura 9. Assume-se que a cardinalida<strong>de</strong> <strong>de</strong> cada uma das dimensões A, B e C é,<br />
respectivamente, 40, 400 e 4000.<br />
Figura 14 - Array 3D para as dimensões A, B e C, dividido em 64 chunks<br />
Os chunks são lidos segundo a or<strong>de</strong>m ABC, do chunk 1 para o chunk 64. Assumindo que o chunk 1 já<br />
está carregado em memória, este é agregado segundo a dimensão C para obter um chunk <strong>de</strong> AB,<br />
segundo a dimensão i para obter um chunk <strong>de</strong> AC e segundo a dimensão A para obter um chunk <strong>de</strong> BC.<br />
Assim, o primeiro chunk <strong>de</strong> AB é agregado para o chunk a0b0 <strong>de</strong> AB, o primeiro chunk <strong>de</strong> AC é agregado<br />
para o chunk a0c0 <strong>de</strong> AC e o primeiro chunk <strong>de</strong> BC é agregado para o chunk b0c0 <strong>de</strong> BC. À medida que<br />
novos chunks são lidos, os chunks obtidos vão sendo agrupados aos chunks dos agregados<br />
correspon<strong>de</strong>ntes. Note-se que os chunks foram lidos segundo a or<strong>de</strong>m (A, B, C), que correspon<strong>de</strong> a uma<br />
or<strong>de</strong>m linear <strong>de</strong>s<strong>de</strong> o chunk 1 ao chunk 64. Isso significa que b0c0 está completamente agregado <strong>de</strong>pois<br />
<strong>de</strong> terem sido lidos os chunks 1 a 4, após o que é guardado em disco e a sua memória é atribuida ao<br />
chunk b1c0. Este, por sua vez, está completamente agregado <strong>de</strong>pois <strong>de</strong> terem sido lidos os chunks 5 a 8,<br />
e assim sucessivamente. Isto significa que apenas um chunk <strong>de</strong> BC se encontra em memória durante o<br />
cálculo do agregado BC. Da mesma forma, é reservada memória para os chunks a0c0, a1c0, a2c0 e a3c0<br />
enquanto são percorridos os primeiros 16 chunks <strong>de</strong> ABC. Para terminar a agregação para o chunk a0c0,<br />
o resultado da agregação dos chunks 1, 5, 9 e 13 são acumulados no chunk a0c0, esses chunks <strong>de</strong> AC<br />
são escritos para disco e a sua memória atribuída a a0c1, a1c1, a2c1 e a3c1 do agregado AC. Por fim, para<br />
calcular o agregado AB é necessário alocar memória para um total <strong>de</strong> 64 chunks. Neste exemplo, para<br />
calcular BC é necessário memória para 1 chunk <strong>de</strong> BC, para calcular AC é necessária memória para 4<br />
chunks <strong>de</strong> AC e para calcular BC é necessário memória para 4 x 4 = 16 chunks <strong>de</strong> AB [Zhao1997].<br />
Genericamente, é necessário alocar |Bc||Cc|u memória para calcular um agregado BC, |Ad||Cc|u para<br />
calcular um agregado AC e |Ad||Bd|u para calcular um agregado AB, em que |Xd| representa o tamanho<br />
<strong>de</strong> uma dimensão X, |Xc| o tamanho do chunk <strong>de</strong> uma dimensão X e u o tamanho <strong>de</strong> cada elemento do<br />
chunk [Zhao1997]. Como o tamanho <strong>de</strong> um chunk <strong>de</strong> uma dimensão é menor que o tamanho <strong>de</strong>ssa<br />
dimensão na maioria dos casos, conclui-se que é possível calcular o cubo alocando uma quantida<strong>de</strong> <strong>de</strong><br />
32
Diferentes or<strong>de</strong>nações <strong>de</strong> dimensões (D1, D2, ..., Dn) po<strong>de</strong>m gerar diferentes MMSTs com diferentes<br />
requisitos a nível <strong>de</strong> memória. Para exemplificar isto, consi<strong>de</strong>re-se um array com quatro dimensões<br />
ABCD com 10 x 10 x 10 x 10 chunks, em que |A| = 10, |B| = 100, |C| = 1000 e |D| = 10000. A figura<br />
seguinte mostra as MMSTs geradas para a or<strong>de</strong>nação <strong>de</strong> dimensões (A, B, C, D) e (D, B, C, A),<br />
respectivamente. Verifica-se que a MMST para a or<strong>de</strong>nação (D, B, C, A) requer aproximadamente 4 Gb<br />
<strong>de</strong> memória, enquanto a MMST para a or<strong>de</strong>nação (A, B, C, D) requer apenas 4 Mb <strong>de</strong> memória. A<br />
disparida<strong>de</strong> entre os requisitos <strong>de</strong> memória <strong>de</strong>ve-se unicamente ao facto da troca entre A e D na<br />
sequência das dimensões.<br />
Figura 16 - Requisitos <strong>de</strong> memória para duas or<strong>de</strong>nações diferentes das dimensões [Zhao1997]<br />
Se a quantida<strong>de</strong> <strong>de</strong> memória disponível for inferior à memória mínima indicada como necessária pela<br />
MMST, isso significa que não será possível reservar memória para algumas sub-árvores da MMST. Por<br />
forma a contornar esta situação, os autores propõem que a MMST seja dividida na sub-árvore<br />
operacional, para a qual existe espaço suficiente em memória, e num conjunto <strong>de</strong> sub-árvores<br />
incompletas, ou seja, aquelas para as quais não existe espaço suficiente em memória. Para <strong>de</strong>cidir por<br />
que or<strong>de</strong>m <strong>de</strong>ve ser atribuída memória a cada uma das sub-árvores, os autores propõem que se utilize<br />
uma heurística segundo a qual a memória começa a ser atribuída a partir da raiz e da direita para<br />
esquerda, por forma a evitar uma computação em múltiplos passos do array <strong>de</strong> maior dimensão.<br />
2.4.3.2 Variante do algoritmo Multi-Way no sistema DBMiner<br />
Devido ao seu bom <strong>de</strong>sempenho, este algoritmo foi integrado no sistema DBMiner [Tam1998]. A i<strong>de</strong>ia<br />
subjacente a este sistema resulta <strong>de</strong> observações na área da pesquisa em bases <strong>de</strong> dados, que<br />
mostram que normalmente as tarefas <strong>de</strong> exploração <strong>de</strong> dados são realizadas sobre extensos conjuntos<br />
34
<strong>de</strong> dados, frequentemente mantidos para outros fins, e que na maioria dos casos os utilizadores não<br />
conseguem estabelecer um objectivo <strong>de</strong>finido. Isto leva a que as interrogações colocadas impliquem a<br />
agregação <strong>de</strong> gran<strong>de</strong>s quantida<strong>de</strong>s <strong>de</strong> dados, o que impossibilita a rapi<strong>de</strong>z <strong>de</strong>sejada na resposta. O<br />
objectivo do sistema proposto seria, portanto, conseguir que as ferramentas <strong>de</strong> data mining<br />
trabalhassem em conjunto com as ferramentas <strong>de</strong> OLAP <strong>de</strong> uma data warehouse por forma a aumentar<br />
a qualida<strong>de</strong> e rentabilida<strong>de</strong> da experiência para o utilizador, numa perspectiva a que foi dado o nome <strong>de</strong><br />
OLAP mining. Um dos principais <strong>de</strong>safios na criação <strong>de</strong> um sistema <strong>de</strong>stes é a necessida<strong>de</strong> <strong>de</strong> uma<br />
implementação eficiente do mecanismo <strong>de</strong> computação e construção do cubo, que permita uma<br />
capacida<strong>de</strong> <strong>de</strong> resposta rápida. Com base no operador CUBE [Gray1997] e no algoritmo Multi-Way<br />
[Zhao1997], Tam propôs um algoritmo <strong>de</strong> computação <strong>de</strong> agregados cujas principais características são<br />
o facto <strong>de</strong> percorrer a relação uma única vez, computar um agregado a partir do menor agregado já<br />
computado, computar simultaneamente o maior número <strong>de</strong> agregados possível e retirar os agregados <strong>de</strong><br />
memória o mais cedo possível <strong>de</strong> forma a libertar memória para a computação <strong>de</strong> outros agregados<br />
[Tam1998]. Em traços gerais, o algoritmo proposto baseia-se no conceito <strong>de</strong> um cubo baseado em<br />
chunks, em que o cubo é armazenado sob a forma uma tabela relacional e os seus chunks armazenados<br />
como tuplos. Para cada chunk, as células são mapeadas para um en<strong>de</strong>reço <strong>de</strong> memória que po<strong>de</strong> ser<br />
guardado como um dos campos do tuplo, <strong>de</strong> forma a que não seja necessário utilizar mecanismos <strong>de</strong><br />
in<strong>de</strong>xação para ace<strong>de</strong>r aos chunks. No fundo, são combinadas características <strong>de</strong> sistemas ROLAP e<br />
MOLAP num único algoritmo.<br />
No trabalho realizado por Tam, o conceito <strong>de</strong> cubo foi <strong>de</strong>senhado tendo em conta um contexto dirigido<br />
por interrogações (query-driven), no qual o número <strong>de</strong> dimensões do cubo não é conhecido enquanto a<br />
interrogação não é submetida. Por essa razão, conceptualmente o cubo é multidimensional mas é<br />
implementado como um array unidimensional. Sendo D0, D1, ..., DN-1 as dimensões <strong>de</strong> um cubo N-<br />
dimensional, é adicionado o valor ALL a cada dimensão Di, tal como <strong>de</strong>scrito por [Gray1997], o que faz<br />
com que qualquer célula em que o valor ALL faça parte do seu en<strong>de</strong>reço corresponda a um agregado.<br />
Este tipo <strong>de</strong> células é <strong>de</strong>signado como célula cubói<strong>de</strong> (cuboid cell), enquanto as restantes células são<br />
consi<strong>de</strong>radas células nucleares (core cells). Os valores <strong>de</strong> cada dimensão são mapeados para<br />
coor<strong>de</strong>nadas <strong>de</strong> tal forma que a dimensão Di corresponda aos valores {di0, di1, ..., di|Di|-1, diALL}. A posição<br />
<strong>de</strong> cada célula do cubo é <strong>de</strong>notada no espaço multidimensional pelo vector V(v0, v1, ..., vN-1), sendo a<br />
magnitu<strong>de</strong> <strong>de</strong> cada vector equivalente ao número <strong>de</strong> dimensões do cubo. Portanto, para uma célula<br />
cubói<strong>de</strong>, o seu en<strong>de</strong>reço contém pelo menos um componente vj tal que vj = |Dj|, j ≥ 0 e j < N. Assim, a<br />
célula cujo en<strong>de</strong>reço é dado pelo vector V(|D0|, ..., |DN-1|) trata-se da célula cubói<strong>de</strong> correspon<strong>de</strong>nte ao<br />
agregado vazio ALL [Tam1998]. Tomando o cubo C tridimensional na figura 12, verifica-se que existem<br />
três dimensões, em que |D0| = 5, |D1| = 4, |D2| = 3, e que os valores para cada dimensão são di0 = 0, di1 =<br />
1 e assim sucessivamente para i = 0,1, 2. A célula cubói<strong>de</strong> com o en<strong>de</strong>reço V(5, 4, 3) correspon<strong>de</strong>,<br />
então, à célula (ALL, ALL, ALL). Seguindo ainda esta notação, a célula com o en<strong>de</strong>reço V(5, 0, 0) guarda<br />
o resultado da soma das medidas das células {V(0, 0, 0), V(1, 0, 0), V(2, 0, 0), V(3, 0, 0), V(4, 0, 0)},<br />
35
enquanto a célula com o en<strong>de</strong>reço V(5, 4, 0) guarda o resultado da soma das medidas das células S1 =<br />
{V(5, 0, 0), V(5, 1, 0), V(5, 2, 0), V(5, 3, 0)} ou das células S2 = {V(0, 4, 0), V(1, 4, 0), V(2, 4, 0), V(3, 4,<br />
0), V(4, 4, 0)}. Desta forma, a célula V(5, 4, 0) <strong>de</strong>pen<strong>de</strong> <strong>de</strong> dois conjuntos <strong>de</strong> células diferentes, ou seja,<br />
S1 e S2 são sub-cubói<strong>de</strong>s potenciais do cubói<strong>de</strong> V(5, 4, 0)<br />
Figura 17 <strong>–</strong> Representação <strong>de</strong> um cubo 3D segundo [Tam1998]<br />
O facto do cubo ser implementado como um array unidimensional significa que as células do cubo C são<br />
or<strong>de</strong>nadas como mostra a tabela <strong>de</strong> tal forma que o en<strong>de</strong>reço V(0, 0, 0) e V(0, 1, 0) estão nas posições 0<br />
e 4, respectivamente, do array; a última célula do cubo C (V(5, 4, 3)) está guardada na posição 119 uma<br />
vez que existem (5 + 1) x (4 + 1) x (3 + 1) = 120 células no total. O mapeamento entre o espaço<br />
multidimensional e o espaço unidimensional é realizado pelos algoritmos Vector-To-In<strong>de</strong>x e In<strong>de</strong>x-To-<br />
Vector [Tam1998].<br />
Tabela 8 <strong>–</strong> Or<strong>de</strong>m das células do cubo no array [Tam1998]<br />
V(0, 0, 0) V(0, 0, 1) ... V(0, 0, |D 2|)<br />
V(0, 1, 0) V(0, 1, 1) ... V(0, 1, |D 2|)<br />
... ... ... ...<br />
V(0, |D 1|, 0) V(0, |D 1|, 1) ... V(0, |D 1|, |D 2|)<br />
V(1, 0, 0) V(1, 0, 1) ... V(1, 0, |D 2|)<br />
... ... ... ...<br />
V(|D 0|, 2, 0) V(|D 0|, 2, 1) ... V(|D 0|, 2, |D 2|)<br />
... ... ... ...<br />
V(|D 0|, |D 1|, 0) V(|D 0|, |D 1|, 1) ... V(|D 0|, |D 1|, |D 2|)<br />
36
Com base no algoritmo <strong>de</strong> Zhao et al, o array é dividido em chunks, cada um dos quais <strong>de</strong>ve ter uma<br />
dimensão que lhe permita existir em memória. No seguimento da notação utilizada, um chunk po<strong>de</strong> ser<br />
um chunk nuclear (core chunk) ou um chunk cubói<strong>de</strong> (cuboid chunk). A maioria dos chunks cubói<strong>de</strong>s são<br />
pequenos e acedidos mais frequentemente, pelo que <strong>de</strong>vem ser separados dos chunks nucleares para<br />
assegurar um acesso rápido aos primeiros. Porém, como nem todos os chunks <strong>de</strong> um cubo têm o<br />
mesmo volume, é necessário <strong>de</strong>terminar qual o tamanho dos chunks. Para esse fim, é estabelecido um<br />
limite e verifica-se se o tamanho da maior dimensão po<strong>de</strong> ser usado como limite para todas as<br />
dimensões. Tomando o exemplo do cubo 3D da figura 12 e assumindo um limite máximo <strong>de</strong> 27 células,<br />
ao seleccionar o valor <strong>de</strong> |D0| = 5 verifica-se que um chunk teria 5 x 4 x 3 = 60 células, o que ultrapassa o<br />
limite pré-estabelecido. A estratégia passa por dividir o valor <strong>de</strong> |D0| por 2 e adicionar 1 ao resultado<br />
obtido, enquanto o valor obtido não respeitar o limite estabelecido [Tam1998]. A figura abaixo mostra o<br />
cubo C após ter sofrido chunking.<br />
Figura 18 <strong>–</strong> Representação do cubo C com 18 chunks [Tam1998]<br />
Cada chunk é tratado como um cubo, o que significa que conceptualmente existem dois mo<strong>de</strong>los<br />
multidimensionais: o mo<strong>de</strong>lo global, que <strong>de</strong>termina os i<strong>de</strong>ntificadores dos chunks, e o mo<strong>de</strong>lo local, que<br />
<strong>de</strong>termina os afastamentos (offsets) das células <strong>de</strong>ntro <strong>de</strong> cada chunk. Logo, cada célula do cubo está<br />
sempre associada a um vector global e um vector local, que po<strong>de</strong>m ser obtidos a partir do en<strong>de</strong>reço da<br />
célula. Tendo em conta a divisão do cubo em chunks, a última célula cubói<strong>de</strong> do cubo C encontra-se em<br />
V(5, 4, 3) e é agora a única célula do chunk 17. Para obter o vector global GV = (gv0, gv1, gv2) para esta<br />
célula, começa-se em v0 e compara-se esse valor com o tamanho do primeiro segmento da dimensão<br />
D0, que é 2 neste caso. Como 5 ≥ 3, toma-se o tamanho do segmento seguinte, que é 2, e como<br />
5 ≥ 3 + 2, termina-se no último segmento e conclui-se que gv0 = 2. Da mesma forma, para as dimensões<br />
37
Figura 20 <strong>–</strong> MNST para o cubo C [Tam1998]<br />
Qualquer nó M num nível i abaixo do nível 0 po<strong>de</strong> ser computado a partir dos nós no nível acima cujas<br />
dimensões contenham todas as dimensões que compõem esse nó. Isto significa que po<strong>de</strong> existir mais<br />
do que um nó a partir no nível i-1 a partir do qual o nó M po<strong>de</strong> ser computado. A razão da existência<br />
<strong>de</strong>sta estrutura pren<strong>de</strong>-se com o facto <strong>de</strong>, em vez <strong>de</strong> seleccionar o nó no nível i-1 que permita calcular o<br />
nó M com menor requisito <strong>de</strong> memória possível, o algoritmo implementado por Tam seleccionar o nó que<br />
requer o menor número possível <strong>de</strong> células cubói<strong>de</strong>s para se conseguir computar o nó M. Segundo esta<br />
lógica e tendo em conta a MNST na figura 15, para computar o agregado ALL seria escolhido o nó 2 e<br />
não o nó 1 uma vez que o nó 2 requer |D2| células e o nó requer |D1| células para computar esse<br />
agregado e |D2| < |D1|. Como razões para o uso <strong>de</strong>sta estrutura em <strong>de</strong>trimento da MMST, são indicadas<br />
a maior facilida<strong>de</strong> na sua construção <strong>de</strong>vido ao facto <strong>de</strong> não ser necessário realizar cálculos <strong>de</strong><br />
requisitos <strong>de</strong> memória, o facto <strong>de</strong> serem estruturas equivalente em termos <strong>de</strong> necessida<strong>de</strong>s <strong>de</strong> memória<br />
e da MNST permitir usar um menor número <strong>de</strong> subcubói<strong>de</strong>s para computar um agregado.<br />
Com base nestes conceitos, Tam propõe um algoritmo <strong>de</strong>signado como R-cubing, cujo funcionamento é<br />
explicado <strong>de</strong> seguida com base na MNST na figura 15. Como a célula em V(0, 0, 0) é uma célula<br />
nuclear, a MNST é percorrida a partir do nó 012 no nível 0. Sabendo que o nó 012 po<strong>de</strong> ser computado a<br />
partir dos nós 01, 02 e 12 segundo as dimensões D2, D1 e D0, respectivamente, a célula V(0, 0, 0) é<br />
adicionada às células cubói<strong>de</strong>s em V(0, 0, 3) segundo a dimensão D2, V(0, 4, 0) segundo a dimensão D1<br />
e V(5, 0, 0) segundo D0. No total, estão três células cubói<strong>de</strong>s em memória. O processo repete-se para a<br />
célula nuclear seguinte em V(0, 0, 1), que é adicionado a V(0, 0, 3), V(0, 4, 1) e V(5, 0 ,1), o que faz com<br />
que mais duas células cubói<strong>de</strong>s sejam carregadas para memória. Da mesma forma, a célula nuclear em<br />
V(0, 0, 2) é adicionada a V(0, 0, 3), V(0, 4, 2) e V(5, 0, 2), forçando o carregamento <strong>de</strong> mais duas células<br />
cubói<strong>de</strong>s para memória. Neste ponto, a célula cubói<strong>de</strong> em V(0, 0, 3) contém todas as somas<br />
39
necessárias, pelo que é necessário verificar na MNST se esta célula é útil para o cálculo <strong>de</strong> outras. Na<br />
MNST, este agregado corrrespon<strong>de</strong> ao nó 01 e não possui quaisquer nós <strong>de</strong>pen<strong>de</strong>ntes <strong>de</strong> si; logo, V(0,<br />
0, 3) é guardado em disco e a memória associada libertada. As células nucleares em V(0, 1, 0), V(0, 1,<br />
1), V(0, 1, 2), V(0, 2, 0), ..., V(0, 3, 1), V(0, 3, 2) são <strong>de</strong>pois examinadas e adicionadas às<br />
correspon<strong>de</strong>ntes células cubói<strong>de</strong>s. Novamente, as células cubói<strong>de</strong>s em V(0, 1, 3), V(0, 2, 3) e V(0, 3, 3)<br />
estão completas e po<strong>de</strong>m ser guardadas em disco. Note-se que, aquando da leitura da célula nuclear<br />
V(0, 3, 0), o valor que contém vai ser adicionado à célula cubói<strong>de</strong> em V(0, 4, 0), o que faz com que esta<br />
célula esteja completa. Segundo a MNST, esta célula cubói<strong>de</strong> refere-se ao nó 02 e <strong>de</strong>le <strong>de</strong>pen<strong>de</strong>m o nó<br />
0 no nível 2. Logo, a célula V(0, 4, 0) é adicionada à célula V(0, 4, 3) segundo a dimensão D2. Este<br />
processo, tal como ilustrado na figura 16, é repetido para cada célula nuclear e cubói<strong>de</strong> até que todas as<br />
células nucleares tenham sido percorridas e todas as células cubói<strong>de</strong>s tenham sido materializadas<br />
[Tam1998]. Como se pô<strong>de</strong> verificar, antes <strong>de</strong> uma célula cubói<strong>de</strong> ser guardada e a memória associada<br />
libertada tem que cumprir dois requisitos: essa célula <strong>de</strong>ve ter sido completamente materializada, ou<br />
seja, <strong>de</strong>ve conter o resultado da soma <strong>de</strong> todas as células subcubói<strong>de</strong>s correspon<strong>de</strong>ntes e já <strong>de</strong>ve ter<br />
sido adicionada a todos os cubói<strong>de</strong>s que <strong>de</strong>la <strong>de</strong>pen<strong>de</strong>m.<br />
Figura 21 <strong>–</strong> Relação entre cubói<strong>de</strong>s e subcubói<strong>de</strong>s em relação à célula V(0, 0, 0) usando R-cubing [Tam1998]<br />
Porém, tal como referido anteriormente, o conceito <strong>de</strong> cubo implementado por Tam é o <strong>de</strong> um cubo<br />
baseado em chunks, pelo que em vez <strong>de</strong> uma célula ser adicionada a outra na realida<strong>de</strong> um chunk<br />
subcubói<strong>de</strong> é adicionado a outro chunk subcubói<strong>de</strong>. Segundo o algoritmo proposto, o chunk 0 é<br />
40
adicionado ao chunk 12 segundo D0, ao chunk 4 segundo D1 e ao chunk 1 segundo D2, tal como mostra<br />
a figura 17. No fundo, o processo <strong>de</strong> somar um chunk subcubói<strong>de</strong> a outro equivale a comprimir esse<br />
subcubói<strong>de</strong> segundo uma dimensão Da <strong>de</strong> tal forma que o vector local da célula subcubói<strong>de</strong> do chunk<br />
passa a ter lva = 0 [Tam1998]. Na situação da figura 17, as células {0, 9, 18} do chunk 0 (LV(0, 0, 0),<br />
LV(1, 0, 0) e LV(2, 0, 0)) são adicionadas à célula 0 do chunk 12 (LV(0, 0, 0)) segundo a dimensão D0; as<br />
células {0, 3, 6} do chunk 0 (LV(0, 0, 0), LV(0, 1, 0) e LV(0, 2, 0)) são adicionadas à célula 0 do chunk 4<br />
segundo a dimensão D1; as células {15, 16, 17} do chunk 0 (LV(1, 2, 0), LV(1, 2, 1) e LV(1, 2, 2)) são<br />
adicionadas à célula 5 do chunk 1 (LV(1, 2, 0)) segundo a dimensão D2.<br />
Figura 22 <strong>–</strong> Processo <strong>de</strong> adição do chunk 0 aos chunks subcubói<strong>de</strong>s relacionados [Tam1998]<br />
Conclui-se, assim, que Tam não implementou o algoritmo Multi-Way tal como proposto por Zhao et al<br />
[Zhao1997], mas antes que se baseou em conceitos básicos, como o chunking, o or<strong>de</strong>namento óptimo<br />
das dimensões e a MMST para <strong>de</strong>senvolver e implementar um algoritmo que combina características<br />
tanto da abordagem ROLAP como da abordagem MOLAP. Apesar <strong>de</strong> provavelmente ter realizado<br />
previamente um estudo sobre o algoritmo Multi-Way como forma <strong>de</strong> analisar os seus pontos fortes e<br />
fracos, não existem quaisquer dados sobre esse estudo ou a implementação usada para tal. No final do<br />
seu trabalho, é feita uma comparação entre o algoritmo implementado e o algoritmo Multi-Way apenas<br />
em termos do tempo <strong>de</strong> execução, que mostra que ambos os algoritmos têm um <strong>de</strong>sempenho<br />
semelhante para conjuntos <strong>de</strong> dados com baixo número <strong>de</strong> dimensões e que o <strong>de</strong>sempenho do<br />
41
algoritmo Multi-Way se <strong>de</strong>teriora quando aumenta o número <strong>de</strong> dimensões em consequência do elevado<br />
custo associado à construção da MMST [Tam1998].<br />
2.5 Variantes ao problema tradicional<br />
Os trabalhos mais recentes na área <strong>de</strong> OLAP e geração <strong>de</strong> hipercubos inci<strong>de</strong>m sobre uma variante do<br />
problema tradicional da computação <strong>de</strong> cubos. Como se viu, o problema tradicional consiste, muito<br />
resumidamente, em calcular todos os agregados da forma mais eficiente possível, tendo em conta que o<br />
problema é exponencial em relação ao número <strong>de</strong> dimensões consi<strong>de</strong>radas. Além disso, há que ter em<br />
atenção que o tamanho <strong>de</strong> cada agregado <strong>de</strong>pen<strong>de</strong> da cardinalida<strong>de</strong> das dimensões que o compõem.<br />
Como os dados reais ten<strong>de</strong>m a ser <strong>de</strong> natureza esparsa, uma estratégia para aumentar o <strong>de</strong>sempenho<br />
dos algoritmos nessas situações passa por i<strong>de</strong>ntificar antes da computação quais os subconjuntos <strong>de</strong><br />
interesse [Beyer1999] apresentaram uma variante ao problema tradicional da geração <strong>de</strong> cubos a que<br />
<strong>de</strong>ram o nome <strong>de</strong> cubos iceberg (iceberg cubes). O problema icerberg-CUBE consiste em computar<br />
todas as agregações para todas as combinações <strong>de</strong> atributos que satisfazem uma <strong>de</strong>terminada<br />
condição, à semelhança da cláusula HAVING numa interrogação SQL. Tendo em conta o contexto <strong>de</strong><br />
dados esparsos, a condição envolvida estabelece que uma partição <strong>de</strong>ve ter pelo menos N tuplos, sendo<br />
N <strong>de</strong>signado como o suporte mínimo da partição.<br />
2.5.1 Computação da base para o topo (bottom-up computation)<br />
Beyer e Ramakrishnan propuseram o algoritmo BUC como resposta ao problema dos cubos iceberg.<br />
Este algoritmo procura combinar a eficiência a nível <strong>de</strong> entradas/saídas do algoritmo Partitioned-Cube<br />
com a possibilida<strong>de</strong> <strong>de</strong> recorrer a filtragem em função do suporte mínimo pretendido [Beyer1999]. A sua<br />
<strong>de</strong>signação <strong>de</strong>ve-se ao facto do algoritmo começar nos agregados mais pequenos e prosseguir até aos<br />
agregados maiores, ao contrário da maioria dos restantes algoritmos. Cada dimensão é lida e dividida<br />
segundo o número <strong>de</strong> ocorrências para cada um dos valores <strong>de</strong>ssa dimensão, sendo as restantes<br />
dimensões computadas recursivamente para cada partição.<br />
O algoritmo recorre à estratégia dividir para conquistar (divi<strong>de</strong>-and-conquer) uma vez que, após uma<br />
<strong>de</strong>terminada partição ter sido calculada, todos os cubói<strong>de</strong>s <strong>de</strong>scen<strong>de</strong>ntes são calculados antes do<br />
algoritmo passar à partição seguinte. O movimento da base para o topo, ou seja, no sentido dos<br />
agregados mais pequenos para os agregados maiores, permite que seja realizada uma filtragem<br />
recorrendo à proprieda<strong>de</strong> anti-monotónica empregue no algoritmo Apriori, usado na <strong>de</strong>scoberta <strong>de</strong><br />
associações frequentes entre objectos [Agrawal1994] que estabelece que, se a contagem numa célula c<br />
<strong>de</strong> um cubói<strong>de</strong> A é inferior a um limite mínimo estabelecido, então o valor para qualquer uma das células<br />
que partilhem com essa célula um prefixo comum nunca será superior ao limite pré-estabelecido; logo,<br />
essas células <strong>de</strong>scen<strong>de</strong>ntes não precisam <strong>de</strong> ser calculadas.<br />
42
Os resultados mostram que o algoritmo BUC apresenta melhor <strong>de</strong>sempenho na computação <strong>de</strong> cubos<br />
esparsos do que o algoritmo Memory-Cube [Beyer1999].<br />
2.5.2 H-cubing<br />
Han et al [Han2001]propuseram um algoritmo orientado para a resolução do problema dos cubos iceberg<br />
mas para a situação específica em que a condição a ser satisfeita pelos agregados envolve uma medida<br />
não distributiva, como a média. O recurso a este tipo <strong>de</strong> medidas, que normalmente não obe<strong>de</strong>cem à<br />
proprieda<strong>de</strong> anti-monotónica, faz com que não possa ser feito filtragem com base nessa proprieda<strong>de</strong>. No<br />
caso concreto da média, o facto <strong>de</strong> o valor médio numa célula c <strong>de</strong> um cubói<strong>de</strong> A ser inferior a um valor<br />
mínimo pré-<strong>de</strong>finido não significa obrigatoriamente que o valor das células <strong>de</strong>scen<strong>de</strong>ntes seja igualmente<br />
inferior.<br />
O algoritmo proposto utiliza uma estrutura em árvore (H-tree) baseada na FP-tree usada pelo algoritmo<br />
FP-growth [Han1999]. São características <strong>de</strong>sta estrutura o facto <strong>de</strong> po<strong>de</strong>r ser construída com um único<br />
varrimento da base <strong>de</strong> dados e a sua completu<strong>de</strong>, no sentido em que a H-tree e respectiva tabela<br />
(hea<strong>de</strong>r table) fornecem toda a informação necessária para calcular um cubo iceberg. Cada nível da<br />
árvore representa uma dimensão no cubói<strong>de</strong> base e cada tuplo <strong>de</strong> d-dimensões compõe um caminho<br />
com d nós na árvore. Os nós que se encontram ao mesmo nível e contêm o mesmo valor estão ligados<br />
entre si. A cada nível está associada uma tabela (hea<strong>de</strong>r table) que regista a frequência <strong>de</strong> cada um dos<br />
valores possíveis das dimensões e mantém ligações aos primeiros nós correspon<strong>de</strong>ntes a esses valores.<br />
Figura 23 - Exemplo <strong>de</strong> uma H-tree [Agrawal1994]<br />
43
A partir <strong>de</strong>sta estrutura, o cubo po<strong>de</strong> ser calculado da base para o topo (bottom-up) ou do topo para a<br />
base (top-down). Em qualquer das estratégias, o algoritmo começa num <strong>de</strong>terminado nível da árvore e<br />
analisa todos os agregados que incluem a dimensão correspon<strong>de</strong>nte a esse nível e as dimensões<br />
correspon<strong>de</strong>ntes aos níveis superiores. A agregação é facilitada pela tabela (hea<strong>de</strong>r table): se o valor<br />
para um <strong>de</strong>terminado nó é inferior ao mínimo estabelecido, a agregação ―salta‖ para o próximo nó<br />
através do ponteiro lateral. A diferença entre as duas estratégias é o ponto <strong>de</strong> entrada do algoritmo, que<br />
é na base da árvore no caso da direcção ascen<strong>de</strong>nte (bottom-up) e no topo da árvore no caso da<br />
direcção <strong>de</strong>scen<strong>de</strong>nte (top-down).<br />
Uma das vantagens <strong>de</strong>ste algoritmo resi<strong>de</strong> exactamente na estrutura da H-tree que, ao eliminar a<br />
duplicação <strong>de</strong> dados, permite que se tire partido da computação simultânea <strong>de</strong> agregados e que sejam<br />
calculadas menos combinações <strong>de</strong> dimensões.<br />
2.5.3 Star-Cubing<br />
Xin et al propuseram um algoritmo que procura combinar os pontos fortes dos algoritmo Multi-Way, BUC<br />
e H-Cubing. Basicamente, o algoritmo Star-Cubing integra as potencialida<strong>de</strong>s da computação da base<br />
para o topo (bottom-up) e do topo para a base (top-down) com algumas técnicas <strong>de</strong> optimização do<br />
<strong>de</strong>sempenho. No que se refere à or<strong>de</strong>m <strong>de</strong> computação global, utiliza um mo<strong>de</strong>lo do topo para a base<br />
(top-down) e este é complementado por uma abordagem da base para o topo (bottom-up) implementada<br />
por uma camada inferior do algoritmo. Esta integração permite que o algoritmo consiga efectuar<br />
agregações sobre várias dimensões sem per<strong>de</strong>r a capacida<strong>de</strong> <strong>de</strong> dividir os agregados pais e realizar<br />
filtragem sobre os agregados filhos que não respeitam a condição iceberg [Xin2003].<br />
Uma das optimizações introduzidas passa pelo conceito <strong>de</strong> dimensões partilhadas, que facilita a<br />
agregação partilhada. Observando a figura 24, verifica-se que todos os nós da árvore mais à esquerda<br />
incluem as dimensões ABC, todos os nós na segunda sub-árvore incluem as dimensões AB e todos os<br />
nós na terceira sub-árvore incluem a dimensão A. A estas dimensões comuns em várias sub-árvores dá-<br />
se o nome <strong>de</strong> dimensões partilhadas.<br />
Figura 24 - Árvore <strong>de</strong> computação top-down [Xin2003]<br />
44
Como as dimensões partilhadas po<strong>de</strong>m ser i<strong>de</strong>ntificadas numa fase inicial, isso significa que po<strong>de</strong> ser<br />
avaliada a necessida<strong>de</strong> <strong>de</strong> computar <strong>de</strong>terminados agregados posteriormente. Se a condição iceberg for<br />
anti-monotónica e o valor agregado numa dimensão partilhada não satisfizer essa condição, todos os<br />
agregados que esten<strong>de</strong>m essa dimensão partilhada não satisfazem igualmente a condição e, como tal,<br />
não precisam <strong>de</strong> ser computados. Esta capacida<strong>de</strong> <strong>de</strong> conseguir <strong>de</strong>terminar o mais cedo possível<br />
durante a computação que <strong>de</strong>terminados agregados não necessitam <strong>de</strong> ser calculados é outra das<br />
optimizações importantes integradas no algoritmo. Outra optimização relevante é o uso <strong>de</strong> uma estrutura<br />
semelhante à H-tree mas com maior capacida<strong>de</strong> <strong>de</strong> compressão (star-tree).<br />
Os resultados a nível <strong>de</strong> <strong>de</strong>sempenho para este algoritmo foram semelhantes aos conseguidos pelo<br />
algoritmo Multi-Way para cubos completos e melhores que os obtidos pelos vários algoritmos para cubos<br />
esparsos, em gran<strong>de</strong> parte <strong>de</strong>vido ao facto do algoritmo conseguir integrar várias optimizações.<br />
45
3 Trabalho realizado<br />
Esta secção <strong>de</strong>screve os principais aspectos da implementação realizada e as alterações propostas ao<br />
algoritmo Multi-Way no sentido <strong>de</strong> aumentar a capacida<strong>de</strong> <strong>de</strong> gestão <strong>de</strong> memória do mesmo e,<br />
consequentemente, o número <strong>de</strong> situações em que po<strong>de</strong> ser aplicado.<br />
3.1 Motivação<br />
O estudo dos trabalhos realizados nesta área mostra que a computação <strong>de</strong> agregados multidimensionais<br />
e agregados é uma operação fundamental no que se refere às aplicações OLAP, tendo sido concebidos<br />
diferentes algoritmos e estratégias <strong>de</strong> optimização para esse fim. Porém, muitos dos algoritmos<br />
anteriormente apresentados foram <strong>de</strong>senvolvidos para sistemas ROLAP, sendo o número <strong>de</strong> algoritmos<br />
<strong>de</strong>senhados para sistemas MOLAP bastante inferior. Os sistemas do tipo MOLAP são mais afectados<br />
pelo carácter esparso dos dados, uma situação frequente na vida real, mas conseguem alcançar uma<br />
eficiência semelhante à dos algoritmos para sistemas ROLAP <strong>de</strong>s<strong>de</strong> que sejam aplicadas técnicas que<br />
lhes permitam lidar com esse tipo <strong>de</strong> dados ou quando são aplicados a conjuntos <strong>de</strong> dados <strong>de</strong> pequena<br />
ou média dimensão.<br />
O algoritmo Multi-Way foi proposto por Zhao et al [Zhao1997] exactamente na sequência da ausência <strong>de</strong><br />
trabalhos nesta área. A i<strong>de</strong>ia básica <strong>de</strong>ste algoritmo resi<strong>de</strong> no aproveitamento das características<br />
inerentes a este tipo <strong>de</strong> sistemas, que pela sua própria organização dispensam a necessida<strong>de</strong> <strong>de</strong><br />
reor<strong>de</strong>nar atributos e efectuar agrupamentos <strong>de</strong> forma a que os primeiros agregados calculados possam<br />
servir <strong>de</strong> base ao cálculo <strong>de</strong> agregados posteriores: o truque consiste em percorrer os valores das<br />
dimensões, armazenados em posições fixas, da forma mais eficiente possível e calcular<br />
simultaneamente o máximo <strong>de</strong> agregados parciais espacialmente <strong>de</strong>limitados que for possível. O<br />
principal problema que se põe a esta abordagem está relacionado com a forma como os arrays vão ser<br />
geridos, uma vez que é necessário carregar e armazenar arrays que provavelmente ultrapassam a<br />
capacida<strong>de</strong> <strong>de</strong> memória existente. Para resolver os problemas <strong>de</strong> gestão <strong>de</strong> memória, os autores<br />
propuseram o uso <strong>de</strong> chunking, por forma a dividir arrays n-dimensionais em fragmentos n-dimensionais<br />
mais pequenos que po<strong>de</strong>m ser armazenados como um único objecto.<br />
Os princípios básicos <strong>de</strong>ste algoritmo, tais como a or<strong>de</strong>nação óptima, o chunking e a MMST, estiveram<br />
na base <strong>de</strong> um algoritmo <strong>de</strong>senvolvido e implementado por Tam [Tam1998], tal como explicado no<br />
<strong>de</strong>correr da secção anterior. Embora na prática o algoritmo se afaste do que foi proposto por Zhao et al,<br />
continua a ser um exemplo válido <strong>de</strong> uma implementação possível baseada nesse conjunto <strong>de</strong><br />
princípios, apesar <strong>de</strong> direccionada e optimizada para um fim específico. Porém, in<strong>de</strong>pen<strong>de</strong>ntemente dos<br />
bons resultados conseguidos, o algoritmo continua a apresentar limitações uma vez que apenas<br />
consegue computar cubos com pequena a média dimensão (com menos <strong>de</strong> <strong>de</strong>z dimensões) [Tam1998].<br />
Tendo em conta a escassez <strong>de</strong> trabalhos direccionados para sistemas MOLAP e os bons resultados<br />
alcançados por este algoritmo, consi<strong>de</strong>rou-se que seria interessante focar o trabalho sobre o algoritmo<br />
46
Multi-Way. Além do algoritmo proposto e do relatório do trabalho realizado por Tam, não existe qualquer<br />
outra informação disponível sobre este algoritmo, assim como não foi possível ter acesso à<br />
implementação realizada. Assim sendo, o objectivo <strong>de</strong>ste trabalho consiste em fazer um estudo<br />
aprofundado do algoritmo Multi-Way, com base na implementação realizada segundo a proposta <strong>de</strong><br />
[Zhao1997], e tentar introduzir nessa implementação optimizações que permitam ao algoritmo ser<br />
efectivo para maiores volumes <strong>de</strong> dados e maiores dimensionalida<strong>de</strong>s.<br />
3.2 Arquitectura<br />
Neste contexto, um cubo multidimensional é representado por dois vectores unidimensionais, em que um<br />
tem comprimento igual ao número <strong>de</strong> dimensões existentes nos dados e mantém em cada posição a<br />
cardinalida<strong>de</strong> da dimensão respectiva e o outro tem comprimento igual ao produto das cardinalida<strong>de</strong>s<br />
das dimensões envolvidas e mantém os valores computados. O vector que guarda a informação sobre<br />
as dimensões fá-lo obe<strong>de</strong>cendo à or<strong>de</strong>nação óptima <strong>de</strong>finida por Zhao et al [Zhao1997]. Esse vector<br />
funciona como um vector <strong>de</strong> controlo na medida em que permite recuperar os valores que estão<br />
guardados no outro vector, usando uma função <strong>de</strong> conversão. Assumindo que temos um cubo com 3<br />
dimensões |A| = 2, |B| = 3, |C| = 4 e preten<strong>de</strong>mos ace<strong>de</strong>r à posição (2, 1, 0) no vector <strong>de</strong> dados, a<br />
posição correspon<strong>de</strong>nte no vector unidimensional é dada pelo produto entre as cardinalida<strong>de</strong>s <strong>de</strong> cada<br />
uma das dimensões e a coor<strong>de</strong>nada que se preten<strong>de</strong> converter relativa a essa dimensão (2 + (3 x 1) +<br />
2 x 3 x 0 = 5). Esta abordagem permite que seja utilizado qualquer tipo <strong>de</strong> função <strong>de</strong> cálculo pois esta foi<br />
<strong>de</strong>finida a partir <strong>de</strong> uma classe genérica abstracta. Para tal, apenas é necessário <strong>de</strong>rivar uma classe<br />
específica para a função pretendida.<br />
No que se refere à forma como os dados são mantidos e utilizados pelo algoritmo, estes são mantidos<br />
numa tabela da base <strong>de</strong> dados que simula uma tabela <strong>de</strong> factos. Essa tabela é composta por um<br />
i<strong>de</strong>ntificador do agregado, uma coluna por dimensão que representa a posição relativa no agregado e o<br />
valor correspon<strong>de</strong>nte a essa posição para esse agregado. A tabela abaixo mostra uma utilização<br />
possível para essa tabela, assumindo que temos um cubo com as dimensões A, B e C em que |A| = |B| =<br />
|C| = 3. Ao lado <strong>de</strong> cada tuplo, está indicado o cubói<strong>de</strong> a que se refere. Como se po<strong>de</strong> verificar, existem<br />
várias entradas para o mesmo cubói<strong>de</strong>, na medida em que cada linha correspon<strong>de</strong> a uma posição<br />
diferente nesse cubói<strong>de</strong>. A necessida<strong>de</strong> do i<strong>de</strong>ntificador advém do facto <strong>de</strong> existirem entradas com<br />
valores iguais para diferentes cubói<strong>de</strong>s. Como exemplo, temos as linhas 7 e 15, em que os valores para<br />
as várias colunas são iguais (2, 0, 0, ..., 0) mas se referem a cubói<strong>de</strong>s diferentes (AB e BC<br />
respectivamente). Desta forma, consegue-se representar qualquer elemento <strong>de</strong> qualquer cubói<strong>de</strong>.<br />
47
Tabela 9 <strong>–</strong> Exemplo <strong>de</strong> notação utilizada para i<strong>de</strong>ntificar os agregados e seus elementos<br />
I<strong>de</strong>ntificador Col001 Col002 Col003 Col004 ... Col010 Valor<br />
AB L000001 0 0 0 0 ... 0 3<br />
AB L000001 0 1 0 0 ... 0 7<br />
AB L000001 0 2 0 0 ... 0 1<br />
AB L000001 1 0 0 0 ... 0 5<br />
AB L000001 1 1 0 0 ... 0 8<br />
AB L000001 1 2 0 0 ... 0 6<br />
AB L000001 2 0 0 0 ... 0 10<br />
AB L000001 2 1 0 0 ... 0 2<br />
AB L000001 2 2 0 0 ... 0 3<br />
AC L000002 0 0 0 0 ... 0 9<br />
AC L000002 0 0 0 0 ... 0 11<br />
... … ... ... … ... ... ... ...<br />
AC L000002 1 2 0 0 ... 0 13<br />
... … ... ... … ... ... ... ...<br />
BC L001002 2 0 0 0 ... 0 12<br />
... … ... ... … ... ... ... ...<br />
Actualmente, a tabela possui no máximo <strong>de</strong>z colunas, uma vez que as tabelas têm que ser construídas<br />
com um número limite <strong>de</strong> colunas. Porém, este valor não coloca qualquer limitação ao algoritmo na<br />
medida em que este não <strong>de</strong>pen<strong>de</strong> do número <strong>de</strong> colunas da tabela, que po<strong>de</strong> ser facilmente alterado,<br />
visto que recebe à partida o número <strong>de</strong> dimensões a tratar.<br />
3.3 Optimização <strong>de</strong> “sub-treeing”<br />
O conceito <strong>de</strong> árvore mínima <strong>de</strong> cobertura (MMST) para um <strong>de</strong>terminado or<strong>de</strong>namento das dimensões é<br />
central no algoritmo, uma vez que assegura que é alocada a quantida<strong>de</strong> mínima <strong>de</strong> memória necessária<br />
para esse or<strong>de</strong>namento das dimensões. A i<strong>de</strong>ia <strong>de</strong>sta optimização passa por optimizar o funcionamento<br />
do algoritmo quando se preten<strong>de</strong> calcular um <strong>de</strong>terminado agregado, uma vez que a topologia do próprio<br />
algoritmo obriga a refazer os cálculos sempre que é realizada um operação OLAP, como drill-down e roll-<br />
up. Logo, quando se preten<strong>de</strong> calcular um <strong>de</strong>terminado agregado, não há necessida<strong>de</strong> <strong>de</strong> calcular todos<br />
os agregados correspon<strong>de</strong>ntes a cada um dos nós da árvore mas somente aqueles que são estritamente<br />
necessários, ou seja, não é necessário calcular toda a árvore mas apenas uma porção <strong>de</strong>sta (sub-tree).<br />
A figura 25 mostra o pseudocódigo correspon<strong>de</strong>nte à implementação da MMST. Para que a árvore<br />
pu<strong>de</strong>sse suportar esta optimização, foi necessário planear uma forma <strong>de</strong> marcar os nós que são<br />
necessários para calcular um agregado por forma a que se distingam dos restantes e possam assim ser<br />
48
facilmente seleccionados para cálculo, o que é conseguido através <strong>de</strong> uma proprieda<strong>de</strong> que mantém em<br />
cada nó da árvore a referência do seu nó pai.<br />
noRaiz {D 1,D 2,...,D n}<br />
listaNos {}<br />
initMMSTree()<br />
listaFilhos {}<br />
genFilhos(noRaiz)<br />
genFilhos(ListaDimensões noPai)<br />
pai noPai<br />
i n<br />
para cada D i em noPai<br />
noFilho noPai excluindo D i<br />
se(not noFilho listaNos)<br />
listaNos listaNos noFilho<br />
listaFilhos listaFilhos noFilho<br />
genFilhos(noFilho)<br />
i i-1<br />
Figura 25 <strong>–</strong> Pseudocódigo correspon<strong>de</strong>nte à criação da MMST<br />
Para implementar esta optimização, é necessário recorrer a um mecanismo básico <strong>de</strong> <strong>de</strong>scoberta <strong>de</strong><br />
caminho (path finding) que permita assinalar quais os nós da árvore que é necessário calcular por forma<br />
a conseguir obter um <strong>de</strong>terminado agregado. Para este efeito, os nós são marcados <strong>de</strong>s<strong>de</strong> o nó<br />
objectivo (calculate = true) até à raiz. Para agilizar o varrimento da árvore, cada nó mantém uma<br />
referência para o nó pai imediatamente acima na árvore, à excepção do nó raiz em que o valor da<br />
proprieda<strong>de</strong> father é nulo.Um exemplo da utilida<strong>de</strong> <strong>de</strong>sta implementação po<strong>de</strong> ser facilmente<br />
concretizado, tendo em conta a MMST da figura 26. Segundo o algoritmo original, para calcular o valor<br />
<strong>de</strong> ALL é necessário calcular um total <strong>de</strong> quinze agregados antes <strong>de</strong> obter o valor <strong>de</strong> ALL, ou seja, é<br />
necessário calcular o valor dos agregados correspon<strong>de</strong>ntes a cada um dos nós da árvore. Utilizando<br />
sub-treeing, o valor do agregado ALL po<strong>de</strong> ser obtido calculando apenas quatro agregados uma vez que<br />
apenas é obrigatório calcular o valor correspon<strong>de</strong>nte aos nós ALL, A (father(ALL) = A), AB<br />
(father(A) = AB) e ABC (father(AB) = ABC).<br />
49
Figura 26 <strong>–</strong> Exemplo <strong>de</strong> uma MMST para O = (A, B, C, D)<br />
O objectivo <strong>de</strong>sta optimização passa por reduzir o número <strong>de</strong> nós que é necessário computar para obter<br />
um <strong>de</strong>terminado agregado <strong>de</strong> uma forma simples, o que terá impacto sobre o tempo necessário para<br />
computar esse agregado visto eliminar a computação <strong>de</strong> nós que não interferem directamente no cálculo.<br />
Esta optimização não tem qualquer correspondência no trabalho realizado por Tam [Tam1998] uma vez<br />
que este se baseia na MNST para gerir a sequência <strong>de</strong> computação dos agregados.<br />
3.4 Optimização <strong>de</strong> “sub-chunking”<br />
Tal como referido anteriormente, os arrays <strong>de</strong> gran<strong>de</strong>s dimensões <strong>de</strong>vem ser armazenados divididos em<br />
chunks, por questões <strong>de</strong> eficiência e <strong>de</strong>sempenho. Esta estratégia permite que todas as dimensões<br />
sejam tratadas <strong>de</strong> forma uniforme, uma vez que o chunking permite dividir um array n-dimensional em<br />
vários chunks n-dimensionais que po<strong>de</strong>m ser armazenados em disco.<br />
Um dos principais problemas que se coloca tanto a este algoritmo como aos restantes algoritmos da<br />
área é a quantida<strong>de</strong> <strong>de</strong> memória que requerem para po<strong>de</strong>r calcular os agregados. Em resultados dos<br />
testes efectuados à sua implementação, Tam refere que o seu algoritmo não conseguia completar os<br />
cálculos para volumes <strong>de</strong> dados superiores a 240000 tuplos com 6 dimensões, apenas conseguindo<br />
computar cubos com maior número <strong>de</strong> dimensões para menores volumes <strong>de</strong> dados [Tam1998].<br />
Tendo em conta a árvore da figura 26, verifica-se que o pior caso correspon<strong>de</strong> ao cálculo do agregado<br />
ABC, que necessita <strong>de</strong> um total <strong>de</strong> blocos <strong>de</strong> memória equivalente ao produto da cardinalida<strong>de</strong> das n-1<br />
primeiras dimensões segundo a or<strong>de</strong>m O (10 x 100 x 1000 = 1000000 blocos <strong>de</strong> memória). A solução<br />
passa por criar um sub-chunk mais pequeno recorrendo ao máximo divisor comum (MDC) das cardinalida<strong>de</strong>s<br />
das dimensões, o que para o exemplo anterior resultaria num total <strong>de</strong> 10 x 10 x 10 = 1000 blocos <strong>de</strong> memória.<br />
Desta forma, é necessário guardar para suporte persistente cada um dos sub-chunks para garantir que os<br />
resultados não são alterados e recuperar o sub-chunk pretendido quando se preten<strong>de</strong> mudar para outro. Isto<br />
50
acarreta forçosamente uma carga a nível <strong>de</strong> operações <strong>de</strong> entrada/saída que tem impacto na velocida<strong>de</strong> <strong>de</strong><br />
<strong>de</strong>sempenho do algoritmo, mas que é compensada pelo facto <strong>de</strong> se conseguir realizar cálculos que doutra<br />
forma não seriam fazíveis. O uso do MDC assegura que é criado o maior bloco possível e garante assim que é<br />
realizado o número mínimo possível <strong>de</strong> operações <strong>de</strong> leitura e escrita. Nos casos em que esta estratégia não<br />
permite ainda que o cálculo seja efectuado por falta <strong>de</strong> memória, é criado um novo sub-chunk cuja dimensão<br />
resulta do quociente entre o máximo divisor comum (MDC) e o mínimo divisor comum (mDC). No pior dos<br />
casos, cada um dos novos sub-chunks correspon<strong>de</strong>rá a 1 bloco <strong>de</strong> memória, mais uma vez assegurando que<br />
o cálculo po<strong>de</strong> ser efectuado em <strong>de</strong>trimento do <strong>de</strong>sempenho.<br />
Convém sublinhar que todo este processo não altera em nada a lógica <strong>de</strong> funcionamento do algoritmo tal<br />
como foi proposto, uma vez que a necessida<strong>de</strong> <strong>de</strong> mudança <strong>de</strong> um sub-chunk para outro é gerida pelo próprio<br />
nó da MMST: cada nó conhece a dimensão do seu sub-chunk e a base actual e sempre que <strong>de</strong>tecta que o<br />
elemento a tratar está fora do âmbito do sub-chunk em memória or<strong>de</strong>na o carregamento do sub-chunk<br />
a<strong>de</strong>quado.<br />
dim {D 1,D 2,...,D n}<br />
maxDC MDC(dim)<br />
mDC mDC(dim)<br />
chunk maxDC<br />
tam D 1 x D 2 x ... x D n-1<br />
MAX número máximo <strong>de</strong> blocos <strong>de</strong> memória possível<br />
base {b 1,b 2,...,b n}<br />
loc {l 1,l 2,...,l n}<br />
enquanto(tam > MAX)<br />
chunk maxDC/mDC<br />
tam chunk n-1<br />
para cada D i em loc<br />
se(l i > b i l i < b i)<br />
guardaSubChunk(loc)<br />
lêSubChunk(loc)<br />
actualiza(loc,val)<br />
Figura 27 - Pseudocódigo que ilustra o mecanismo <strong>de</strong> sub-chunking<br />
51
4 Estudo do algoritmo Multi-Way<br />
Esta secção <strong>de</strong>screve os resultados obtidos na sequência do estudo do algoritmo Multi-Way, incluindo<br />
também os efeitos das optimizações propostas na secção 3. Para realizar o estudo, foram realizados<br />
testes no sentido <strong>de</strong> avaliar a influência da <strong>de</strong>nsida<strong>de</strong> dos dados e do volume dos dados sobre o<br />
algoritmo com e sem as optimizações propostas. A nível da análise da influência do volume <strong>de</strong> dados,<br />
foram ainda estudados dois níveis <strong>de</strong> variação diferentes <strong>de</strong>vido à natureza específica do problema, ou<br />
seja, o volume <strong>de</strong> dados submetidos ao algoritmo foi variado tanto em termos do número <strong>de</strong> dimensões<br />
existentes como em termos do número <strong>de</strong> valores comportados por cada dimensão. Na sequência dos<br />
testes, foram recolhidos dados sobre o número <strong>de</strong> leituras e escritas realizadas na base <strong>de</strong> dados, o<br />
tempo <strong>de</strong> execução total e individualizado para cada etapa do algoritmo e o número <strong>de</strong> nós da estrutura<br />
base explorados para realizar o cálculo do cubo.<br />
4.1 Dados <strong>de</strong> teste<br />
Os dados utilizados para realizar o estudo do algoritmo foram gerados recorrendo ao projecto Illimine 2 .<br />
Trata-se <strong>de</strong> um projecto mantido pelo grupo <strong>de</strong> pesquisa em exploração <strong>de</strong> dados (data mining) da<br />
<strong>Universida<strong>de</strong></strong> <strong>de</strong> Illinois li<strong>de</strong>rado pelo professor Jiawei Han que reúne diversas ferramentas nas áreas <strong>de</strong><br />
data mining e aprendizagem, disponibilizando mesmo via internet <strong>de</strong>monstrações <strong>de</strong> alguns dos<br />
principais algoritmos nessa área. Igualmente disponibilizado por este projecto está um gerador aleatório<br />
<strong>de</strong> dados, no qual o utilizador po<strong>de</strong> especificar o número <strong>de</strong> transacções que preten<strong>de</strong>, o número <strong>de</strong><br />
dimensões e a cardinalida<strong>de</strong> <strong>de</strong> cada dimensão.<br />
Seguidamente, foi <strong>de</strong>finido um plano <strong>de</strong> testes que nos permitisse avaliar os aspectos referidos<br />
anteriormente, nomeadamente a influência da <strong>de</strong>nsida<strong>de</strong> e quantida<strong>de</strong> <strong>de</strong> dados submetidos ao<br />
algoritmo, tal como mostra a tabela abaixo. Cada um dos testes, à execpção dos testes T1 a T4<br />
inclusivé, foi executado para a implementação realizada do algoritmo original (MW), para a<br />
implementação com cada uma das optimizações propostas (MW + SC e MW + ST) e para a<br />
implementação reunindo as duas optimizações (MW + SC + ST). Em cada um dos testes, proce<strong>de</strong>u-se<br />
ao cálculo do agregado ALL por forma a forçar o algoritmo a percorrer o maior número possível <strong>de</strong> níveis<br />
da MMST e utilizar o maior bloco <strong>de</strong> memória necessário para efectuar esse cálculo.<br />
2 http://illimine.cs.uiuc.edu<br />
52
Tabela 10 <strong>–</strong> Plano <strong>de</strong> testes<br />
Teste Nº <strong>de</strong> transacções Dimensões Cardinalida<strong>de</strong>s<br />
T1 60000 4 10 20 30 40<br />
T2 120000 4 10 20 30 40<br />
T3 180000 4 10 20 30 40<br />
T4 240000 4 10 20 30 40<br />
T5 5000 3 10 10 10<br />
T6 5000 4 10 10 10 10<br />
T7 5000 5 10 10 10 10 10<br />
T8 5000 3 10 10 10<br />
T9 5000 3 20 20 20<br />
T10 5000 3 30 30 30<br />
T11 5000 3 40 40 40<br />
T12 5000 3 50 50 50<br />
T13 5000 3 60 60 60<br />
T14 5000 3 70 70 70<br />
T15 5000 3 80 80 80<br />
T16 5000 3 90 90 90<br />
Em seguida apresentam-se os resultados obtidos após a concretização do plano <strong>de</strong> testes apresentado<br />
na tabela 9, assim como a análise dos mesmos. Os testes foram realizados num Pentium IV a 3Ghz com<br />
1 Gb <strong>de</strong> memória, com sistema operativo Windows XP Professional.<br />
4.2 Estudo do efeito da variação na <strong>de</strong>nsida<strong>de</strong> dos dados<br />
Para avaliar o impacto da variação da <strong>de</strong>nsida<strong>de</strong> dos dados no <strong>de</strong>sempenho do algoritmo, foram<br />
realizados os testes T1 a T4. Como se po<strong>de</strong> observar tendo em atenção as características dos ficheiros<br />
utilizados, todos eles apresentam o mesmo número <strong>de</strong> dimensões com a mesma cardinalida<strong>de</strong>. A<br />
variação na <strong>de</strong>nsida<strong>de</strong> foi conseguida variando o número <strong>de</strong> transacções consi<strong>de</strong>radas. Os ficheiros<br />
para os testes T1, T2 e T3 foram <strong>de</strong>pois obtidos usando uma percentagem crescente do número máximo<br />
<strong>de</strong> transacções dado pelo produto das cardinalida<strong>de</strong>s das dimensões (10 x 20 x 30 x 40 = 240000),<br />
respectivamente 25%, 50% e 75% <strong>de</strong>sse valor. O gráfico abaixo mostra os resultados obtidos para os<br />
testes T1 a T4 no que se refere ao número total <strong>de</strong> leituras e escritas realizadas na base <strong>de</strong> dados pela<br />
implementação do algoritmo original.<br />
53
T4<br />
T3<br />
T2<br />
T1<br />
0 50000 100000 150000 200000 250000 300000 350000<br />
Figura 28 <strong>–</strong> Efeito da variação da <strong>de</strong>nsida<strong>de</strong> dos dados no número <strong>de</strong> leituras e escritas efectuadas por MW<br />
Como se po<strong>de</strong> constatar da observação do gráfico, in<strong>de</strong>pen<strong>de</strong>ntemente da <strong>de</strong>nsida<strong>de</strong> dos dados, o<br />
algoritmo efectua sempre o mesmo número <strong>de</strong> operações <strong>de</strong> leitura e escrita. Embora este facto possa à<br />
partida parecer <strong>de</strong>sconcertante, <strong>de</strong>corre da própria lógica <strong>de</strong> funcionamento do algoritmo, já que é feito<br />
um varrimento <strong>de</strong> todas as dimensões, começando na dimensão <strong>de</strong> maior cardinalida<strong>de</strong>, e visitadas<br />
todas as posições, uma vez que não se dispõe <strong>de</strong> qualquer informação sobre o seu conteúdo.<br />
Consequentemente, o número <strong>de</strong> operações <strong>de</strong> leitura e escrita realizadas pelo algoritmo apenas<br />
<strong>de</strong>pen<strong>de</strong> do produto das cardinalida<strong>de</strong>s das dimensões envolvidas, <strong>de</strong>s<strong>de</strong> que os dados apresentem o<br />
mesmo número <strong>de</strong> dimensões . O mesmo raciocínio se aplica ao gráfico da figura 29, que apresenta os<br />
tempos <strong>de</strong> cálculo do cubo para diferentes <strong>de</strong>nsida<strong>de</strong>s dos dados <strong>de</strong> entrada.<br />
00:02:44<br />
00:02:26<br />
00:02:09<br />
00:01:52<br />
00:01:35<br />
00:01:17<br />
00:01:00<br />
T1 T2 T3 T4<br />
Escritas<br />
Leituras<br />
Figura 29 <strong>–</strong> Efeito da variação da <strong>de</strong>nsida<strong>de</strong> dos dados no tempo usado por MW para calcular o cubo<br />
54
Uma vez que as restantes implementações do algoritmo seguem a mesma filosofia por se basearem<br />
nele, as conclusões obtidas seriam exactamente as mesmas no que se refere à influência da <strong>de</strong>nsida<strong>de</strong><br />
dos dados no <strong>de</strong>sempenho do algoritmo.<br />
4.3 Estudo do efeito da variação do volume <strong>de</strong> dados<br />
A variação do volume <strong>de</strong> dados po<strong>de</strong> ser consequência da variação do número <strong>de</strong> dimensões que<br />
compõem os dados ou da variação da cardinalida<strong>de</strong> das dimensões envolvidas, pelo que é necessário<br />
analisar cada uma das situações separadamente.<br />
4.3.1 Efeito da variação do número <strong>de</strong> dimensões<br />
Para avaliar o impacto da variação da <strong>de</strong>nsida<strong>de</strong> dos dados no <strong>de</strong>sempenho do algoritmo, foram<br />
realizados os testes T5 a T7, cujos resultados são apresentados <strong>de</strong> seguida. O gráfico 30 apresenta os<br />
resultados dos testes para o algoritmo MW, enquanto os gráficos 31 e 32 fazem o comparativo entre os<br />
resultados obtidos para as diferentes implementações.<br />
180000<br />
160000<br />
140000<br />
120000<br />
100000<br />
80000<br />
60000<br />
40000<br />
20000<br />
0<br />
T5 T6 T7<br />
Leituras 1330 14640 161050<br />
Escritas 836 9596 66006<br />
Figura 30 <strong>–</strong> Efeito da variação do número <strong>de</strong> dimensões nas leituras e escritas realizadas para o algoritmo MW<br />
55
250000<br />
200000<br />
150000<br />
100000<br />
50000<br />
0<br />
T5 T6 T7<br />
MW 1330 14640 161050<br />
MW+ST 1110 11110 111110<br />
MW+SC 1330 14640 226210<br />
MW+ST+SC 1110 11110 124960<br />
140000<br />
120000<br />
100000<br />
80000<br />
60000<br />
40000<br />
20000<br />
0<br />
Leituras<br />
Escritas<br />
T5 T6 T7<br />
MW 836 9596 66006<br />
MW+ST 616 6066 16066<br />
MW+SC 836 9596 126211<br />
MW+ST+SC 616 6066 24961<br />
Figura 31 <strong>–</strong> Efeito da variação do número <strong>de</strong> dimensões nas leituras e escritas realizadas<br />
Como se po<strong>de</strong> verificar da observação dos gráficos, o número <strong>de</strong> leituras e escritas aumenta quando<br />
aumenta o número <strong>de</strong> dimensões consi<strong>de</strong>radas. Porém, esta variação é explicada pelo facto <strong>de</strong>, quando<br />
existem mais dimensões, existem consequentemente mais agregados, que por sua vez correspon<strong>de</strong>m a<br />
um maior número <strong>de</strong> nós na MMST. Da mesma forma, é possível observar que, sempre que se utilize<br />
sub-treeing (ST), o número <strong>de</strong> leituras e escritas é inferior ao verificado para a implementação original,<br />
uma vez que o objectivo <strong>de</strong>sta optimização é exactamente diminuir o número <strong>de</strong> nós que é necessário<br />
explorar para calcular um <strong>de</strong>terminado agregado, reduzindo consequentemente esse tipo <strong>de</strong> operações.<br />
Adicionalmente, verifica-se que sempre que se utiliza apenas sub-chunking (SC) há um aumento no<br />
número <strong>de</strong> leituras e escritas, que advém do facto <strong>de</strong> ser necessário subdividir blocos <strong>de</strong> memória e isso<br />
implicar um maior número <strong>de</strong> leituras e escritas intermédias na base <strong>de</strong> dados para se computar o<br />
mesmo agregado. Quando as duas optimizações são utilizadas em conjunto, verifica-se uma melhoria<br />
56
em relação ao original mas uma <strong>de</strong>terioração em relação à implementação que apenas utiliza sub-<br />
treeing.<br />
Outra medida com interesse para o estudo do efeito da variação do número <strong>de</strong> dimensões correspon<strong>de</strong> à<br />
contabilização dos nós da MMST que são explorados por cada uma das implementações do algoritmo.<br />
As figuras 32 e 33 mostram o efeito da variação do número <strong>de</strong> dimensões no número <strong>de</strong> nós explorados<br />
para o algoritmo MW e para as diferentes implementações, respectivamente.<br />
35<br />
30<br />
25<br />
20<br />
15<br />
10<br />
5<br />
0<br />
T5 T6 T7<br />
MW 8 16 32<br />
Figura 32 - Efeito da variação do número <strong>de</strong> dimensões no número <strong>de</strong> nós da MMST explorados para o algoritmo MW<br />
35<br />
30<br />
25<br />
20<br />
15<br />
10<br />
5<br />
0<br />
T5 T6 T7<br />
MW 8 16 32<br />
MW+ST 4 5 6<br />
MW+SC 8 16 32<br />
MW+SC+ST 4 5 6<br />
Figura 33 <strong>–</strong> Efeito da variação do número <strong>de</strong> dimensões no número <strong>de</strong> nós da MMST explorados<br />
Verifica-se facilmente, tal como seria esperado, que a um maior número <strong>de</strong> dimensões nos dados<br />
correspon<strong>de</strong> igualmente um maior número <strong>de</strong> nós da MMST explorados, tal como referimos na análise<br />
57
dos gráficos anteriores. Esse acréscimo é mais acentuado nas implementações que não empregam<br />
sub-treeing, o que confirma novamente o que havíamos constatado na análise do gráfico anterior.<br />
O gráfico seguinte ilustra a influência do aumento do número <strong>de</strong> dimensões no tempo necessário para o<br />
algoritmo calcular o agregado ALL. Como se po<strong>de</strong> verificar, o tempo dispendido nesse cálculo aumenta<br />
com o número <strong>de</strong> dimensões envolvidas, o que confirma igualmente os resultados apresentados por<br />
Tam [Tam1998].<br />
00:02:01<br />
00:01:44<br />
00:01:26<br />
00:01:09<br />
00:00:52<br />
00:00:35<br />
00:00:17<br />
00:00:00<br />
Figura 34 <strong>–</strong> Efeito da variação do número <strong>de</strong> dimensões no tempo <strong>de</strong> cálculo do cubo<br />
É vísivel que o tempo <strong>de</strong> execução do algoritmo é sempre superior para as implementações que<br />
empregam a optimização <strong>de</strong> sub-chunking, o que seria expectável. Para volumes <strong>de</strong> dados menores,<br />
essas alterações não são tão notórias, tornando-se mais vísiveis para volumes <strong>de</strong> dados maiores.<br />
Verifica-se também que o <strong>de</strong>sempenho é inferior quando se utiliza apenas sub-chunking do que quando<br />
se utilizam ambas as optimizações. Isto <strong>de</strong>ve-se ao facto <strong>de</strong> a introdução do sub-treeing apenas trazer<br />
benefícios a nível do <strong>de</strong>sempenho, na medida em que permite reduzir o número <strong>de</strong> nós explorados na<br />
árvore, mas a introdução do sub-chunking gerar uma <strong>de</strong>gradação a nível do <strong>de</strong>sempenho do algoritmo,<br />
na medida em que o facto <strong>de</strong> ser necessário subdividir blocos <strong>de</strong> memória implica um maior número <strong>de</strong><br />
leituras e escritas na base <strong>de</strong> dados, tal como comprovado nos gráficos 30 e 31.<br />
4.3.2 Efeito da variação da cardinalida<strong>de</strong> das dimensões<br />
Para avaliar o impacto da variação da <strong>de</strong>nsida<strong>de</strong> dos dados no <strong>de</strong>sempenho do algoritmo, foram<br />
realizados os testes T8 a T16. Tendo em conta o objectivo <strong>de</strong>stes testes, não são apresentados<br />
resultados relativos ao número <strong>de</strong> nós explorados visto que, tal como mostrámos na secção 4.2, o<br />
número <strong>de</strong> nós explorados mantém-se constante <strong>de</strong>s<strong>de</strong> que o número <strong>de</strong> dimensões envolvidas seja o<br />
mesmo, que se verifica nesta situação.<br />
MW MW+ST MW+SC MW+ST+SC<br />
T5<br />
T6<br />
T7<br />
58
As figuras 35 e 36 mostram o efeito da variação da cardinalida<strong>de</strong> das dimensões no número <strong>de</strong> leituras e<br />
escritas realizadas pelo algoritmo para diferentes optimizações, respectivamente.<br />
1000000<br />
100000<br />
10000<br />
1000<br />
100<br />
10<br />
1<br />
T8 T9 T10 T11 T12 T13 T14 T15 T16<br />
MW 1330 9260 29790 68920 132650 226980 357910 531440 571280<br />
MW+ST 1110 8420 27930 65640 127550 219660 347970 518480 538880<br />
MW+SC 1330 9260 31710 72280 183050 249660 453670 571280 753570<br />
MW+SC+ST 1110 8420 28920 67360 155000 231360 399000 538880 737190<br />
Figura 35 <strong>–</strong> Efeito da variação da cardinalida<strong>de</strong> das dimensões no número <strong>de</strong> leituras efectuadas<br />
1000000<br />
100000<br />
10000<br />
1000<br />
100<br />
10<br />
1<br />
Leituras<br />
Escritas<br />
T8 T9 T10 T11 T12 T13 T14 T15 T16<br />
MW 836 3238 5766 7896 10626 13956 17886 22416 59281<br />
MW+ST 616 2398 3906 4616 5526 6636 7946 9456 26881<br />
MW+SC 836 3238 4711 8281 58051 33661 110671 59281 27546<br />
MW+SC+ST 616 2398 1921 3361 30001 15361 56001 26881 11166<br />
Figura 36 - Efeito da variação da cardinalida<strong>de</strong> das dimensões no número <strong>de</strong> escritas efectuadas<br />
Constata-se que, à medida que aumenta a cardinalida<strong>de</strong> das dimensões envolvidas, o número <strong>de</strong><br />
leituras e escritas aumenta também drasticamente, sendo o acréscimo no número <strong>de</strong> leituras sempre<br />
59
superior ao aumento do número <strong>de</strong> escritas. Mantem-se a tendência verificada nos testes anteriores, em<br />
que a implementação que apenas emprega sub-treeing realiza um menor número <strong>de</strong> leituras e escritas e<br />
a implementação que apenas usa sub-chunking realiza mais leituras e escritas que o algoritmo original.<br />
Contudo, verifica-se que o uso conjunto das duas implementações implica um número <strong>de</strong> leituras e<br />
escritas inicialmente próximo do da implementação original mas, à medida que aumenta a cardinalida<strong>de</strong><br />
das dimensões, passa a realizar um maior número <strong>de</strong>stas operações quando comparada com a<br />
implementação original ou a que utiliza apenas sub-treeing.<br />
Estes resultados levantam a questão <strong>de</strong> qual a verda<strong>de</strong>ira utilida<strong>de</strong> <strong>de</strong>stas optimizações, se na prática<br />
conduzem à realização <strong>de</strong> um maior número <strong>de</strong> operações <strong>de</strong> leitura e escrita e , consequentemente, a<br />
maiores tempos <strong>de</strong> execução do algoritmo. O gráfico abaixo respon<strong>de</strong> a esta questão, ao mostrar que a<br />
partir <strong>de</strong> um <strong>de</strong>terminado volume <strong>de</strong> dados (2 560 000 tuplos com 4 dimensões) o algoritmo original não<br />
consegue efectuar o cálculo do agregado. Esta situação verificava-se igualmente na implementação <strong>de</strong><br />
Tam [Tam1998], que não conseguia completar os cálculos para volumes <strong>de</strong> dados superiores a 240000<br />
tuplos com 6 dimensões.<br />
00:23:02<br />
00:20:10<br />
00:17:17<br />
00:14:24<br />
00:11:31<br />
00:08:38<br />
00:05:46<br />
00:02:53<br />
00:00:00<br />
MW MW+ST MW+SC MW+SC+ST<br />
Figura 37 <strong>–</strong> Tempo consumido no cálculo do agregado pelas diferentes implementações para 2560000 tuplos<br />
Como se po<strong>de</strong> observar, o algoritmo original e a implementação que apenas emprega sub-treeing<br />
apresentam um tempo <strong>de</strong> cálculo igual a 0, o que na prática significa que não conseguiram efectuar o<br />
cálculo por falta <strong>de</strong> memória. Apenas as implementações que realizam sub-chunking conseguiram<br />
computar o agregado com sucesso, apresentando a implementação que emprega ambas as<br />
optimizações um <strong>de</strong>sempenho melhor. Com efeito, foi esta a razão pela qual foram <strong>de</strong>senvolvidas e<br />
introduzidas as optimizações referidas: apesar <strong>de</strong> não contribuirem para o <strong>de</strong>sempenho do algoritmo<br />
quando comparado com a sua versão original, são <strong>de</strong>cisivas no sentido em que permitem efectuar<br />
cálculos em situações em que o algoritmo original não consegue respon<strong>de</strong>r.<br />
60
Por fim, o gráfico da figura 38 mostra o efeito da variação da cardinalida<strong>de</strong> das dimensões no tempo <strong>de</strong><br />
cálculo do cubo. Para qualquer uma das implementações, a tendência é para um crescimento<br />
exponencial do tempo utilizado para calcular o cubo. Essa tendência é mais clara para a implementação<br />
original quando comparada com a implementação que apenas emprega sub-chunking.<br />
00:04:19<br />
00:03:36<br />
00:02:53<br />
00:02:10<br />
00:01:26<br />
00:00:43<br />
00:00:00<br />
Figura 38 <strong>–</strong> Efeito da variação da cardinalida<strong>de</strong> das dimensões no tempo <strong>de</strong> cálculo do cubo<br />
Os tempos <strong>de</strong> execução para esta implementação do algoritmo são afectados pelo facto <strong>de</strong> ser<br />
necessário diminuir o tamanho do sub-chunk à medida que aumenta o volume <strong>de</strong> dados, o que acarreta<br />
a realização <strong>de</strong> um maior número <strong>de</strong> leituras e escritas e se reflecte na forma mais ―aci<strong>de</strong>ntada‖ da<br />
curva. Esta causalida<strong>de</strong> é comprovada pelos gráficos das figuras 39 e 40.<br />
800000<br />
700000<br />
600000<br />
500000<br />
400000<br />
300000<br />
200000<br />
100000<br />
0<br />
T8 T9 T10 T11 T12 T13 T14 T15 T16<br />
T8 T9 T10 T11 T12 T13 T14 T15 T16<br />
Figura 39- Comparação entre as leituras realizadas para diferentes cardinalida<strong>de</strong>s <strong>de</strong> dimensões<br />
MW<br />
Leituras<br />
MW<br />
MW+ST<br />
MW+ST<br />
MW+SC<br />
MW+SC+ST<br />
61
120000<br />
100000<br />
80000<br />
60000<br />
40000<br />
20000<br />
0<br />
T8 T9 T10 T11 T12 T13 T14 T15 T16<br />
Escritas<br />
Figura 40 <strong>–</strong> Comparação entre as escritas realizadas para diferentes cardinalida<strong>de</strong>s <strong>de</strong> dimensões<br />
MW<br />
MW+ST<br />
MW+SC<br />
MW+SC+ST<br />
62
5 Balanço final<br />
O objectivo do presente trabalho consistiu em realizar um estudo <strong>de</strong>talhado do algoritmo Multi-Way,<br />
assim como das optimizações propostas por forma a que este pu<strong>de</strong>sse ser aplicado com sucesso a<br />
gran<strong>de</strong>s volumes <strong>de</strong> dados, o que não era possível com a sua implementação tal como proposto.<br />
Infelizmente, não foi possível ter acesso a outras implementações como forma <strong>de</strong> estabelecer mais<br />
comparações, estando apenas disponíveis o artigo <strong>de</strong> proposta do algoritmo Multi-Way [Zhao1997] e o<br />
relatório do trabalho realizado por Tam [Tam1998], no qual é <strong>de</strong>scrita uma variante do algoritmo<br />
disponibilizado no sistema DBMiner. Como tal, optou-se por implementar o algoritmo original e,<br />
adicionalmente, duas optimizações no sentido <strong>de</strong> fazer com que o algoritmo pu<strong>de</strong>sse computar cubos a<br />
partir <strong>de</strong> gran<strong>de</strong>s volumes <strong>de</strong> dados. As optimizações propostas foram as seguintes:<br />
A optimização <strong>de</strong>signada como sub-treeing, que está relacionada com a estrutura <strong>de</strong> dados<br />
básica do algoritmo (MMST) e que permite que o algoritmo explore um número menor <strong>de</strong> nós, o<br />
que provoca um acréscimo no <strong>de</strong>sempenho do mesmo<br />
A optimização <strong>de</strong>signada como sub-chunking, que altera ligeiramente uma das estratégias<br />
adoptadas pelo algoritmo para gerir o tamanho dos arrays <strong>de</strong> forma a que seja sempre<br />
aplicável, in<strong>de</strong>pen<strong>de</strong>ntemente da dimensão dos dados e da memória existente. Porém, como<br />
consequência <strong>de</strong>sta optimização, o algoritmo necessita <strong>de</strong> realizar operações <strong>de</strong> leitura e<br />
escritas adicionais sobre a base <strong>de</strong> dados, o que resulta num <strong>de</strong>créscimo do <strong>de</strong>sempenho.<br />
Assim, verifica-se que apesar da aplicação conjunta das duas optimizações não aumentar o<br />
<strong>de</strong>sempenho do algoritmo, a sua aplicação tem um impacto <strong>de</strong>cisivo a nível do seu potencial. Isto <strong>de</strong>ve-<br />
se fundamentalmente ao facto <strong>de</strong> que as optimizações propostas tornam possível a execução do<br />
algoritmo em situações nas quais, tanto a sua implementação original como a variante proposta por Tam,<br />
não conseguem obter resultados por falta <strong>de</strong> memória.<br />
63
6 Referências<br />
[Agrawal1994] Agrawal, Rakesh; Ramakrishnam Srikant. ―Fast Algorithms for Mining Association Rules.‖<br />
Proceedings of the 20th International Conference on VLDB. Santiago, 1994<br />
[Agrawal1996] Agrawal, Sameet, et al. ―On The Computation of Multidimensional Aggregates.‖<br />
Proceeddings of the 22nd VLDB Conference, pp. 506-521, 1996<br />
[Beyer1999] Beyer, Kevin; Raghu Ramakrishnam. ―Bottom-Up Computation of Sparse and Iceberg<br />
CUBEs.‖ Proceedings of ACM SIGMOD, 1999<br />
[Chauduri1997] Chanduri, Surajit; Umeshwar Dayal. ―An Overview of Data Warehousing and OLAP<br />
Technology.‖ ACM SIGMOD Record 26, n.º 1, pp. 65-74, 1997<br />
[Gray1997] Gray, Jim, Surajit Chaduri, Adam Bosworth, Andrew Layman, Don Reichart; Murali<br />
Venkatrao. ―Data Cube: A Relational Aggregation Operator Generalizing Group-By, Cross-Tab and Sub-<br />
Totals.‖ Journal of Data Mining and Knowledge Discovery 1, n.º 1, pp. 29—53, 1997<br />
[Han1999] Han, Jiawei, Jian Pei, e Yiwen Yin. ―Mining Frequent Patterns Without Candidate Generation.‖<br />
Technical Report TR-99-12, Department of Computer Science, Simon Fraser University, 1999<br />
[Han2001a] Han, Jiawei; Micheline Kamber. Data Mining: Concepts and Techniques. Morgan Kaufmann,<br />
2001<br />
[Han2001b] Han, Jiawei, Jian Pei, Guozhu Dong, e Ke Wang. ―Efficient Computation of Iceberg Cubes<br />
With Complex Measures.‖ Proceedings of the International Conference on Management of Data, 2001<br />
[Harinarayan1996] Harinarayan, Venkv; Anand Rajaraman; Jeffrey D. Ullman. ―Implementing Data Cubes<br />
Efficiently‖ Proceedings of ACM-SIGMOD International Conference on Management of Data, Montréal,<br />
pp. 205—216, 1996<br />
[Inmon1996] Inmon, W. H.; ―Building the Data Warehouse‖, John Wiley & Sons, New York, 1996<br />
[Ross1997] Ross, Kenneth A.; Divesh Srivastava. ―Fast Computation of Sparse Datacubes‖. Proceedings<br />
of 23rd VLDB Conference, Atenas, pp. 116—125, 1997<br />
[Tam1998] Tam, Yin Jenny. ―Datacube: Its Implementation and Application in OLAP Mining.‖ MSC tese,<br />
Simon Fraser University, 1998<br />
[Xin 2003] Xin, Dong; Jiawei Han; Xiao Lei Li; Benjamin W. Wah. ―Star-Cubing: Computing Iceberg<br />
Cubes by Top-Down and Bottom-Up Integration‖ Berlim, 2003<br />
64
[Zhao1997] Zhao, Yihong; Prasad M. Deshpan<strong>de</strong>; Jeffrey F. Naughton. ―An Array Based Algorithm for<br />
Simultaneous Multidimensional Aggregates‖. Proceedings of ACM-SIGMOD International Conference on<br />
Management of Data, Tucson, pp. 159—170, 1997<br />
65