quinta-feira, 26 de agosto de 2010


Estrutura B-Tree

Antes de começarmos a falarmos de índice no SQL, devemos primeiro entender a sua utilidade e o conceito de B-tree. O índice foi introduzido no SQL para facilitar as consultas à base de dados. Isso porque muitas vezes em tabelas com uma grande quantidade de registros, o processamento das consultas era muito demorado.

Compreendido de forma simples a utilidade dos índices, vamos botar a mão na massa e explicar como os índices são organizados.

· Como os índices são organizados?

Tanto o índice clusterizado como o índice não-clusterizado se baseiam na estrutura conhecida com B-Tree.

Entendendo o B-Tree:


Na figura acima, vocês podem observar de forma simplificada o funcionamento de uma estrutura B-Tree. Imagine que existe no seu banco de dados 2000 números cadastrados, que variam de 1 a 2000. (Não que isso tenha alguma utilidade, mais só a titulo de exemplo).

Dessa maneira, o SQL inicialmente alocaria todos os números em uma página (Lembrando que o conceito de página foi tratado no post anterior). Como sabemos uma página comporta até 8168 bytes, sendo que apenas 8060 estão reservados para armazenar os dados, já que o restante é reservado para guardar informações relativas à localização da página. Sendo assim, vamos pensar.

Se um dado do tipo INT ocupa 4 bytes de memória, poderíamos armazenar até 2015 linhas nesta página (já que 4 * 2015 = 8060 bytes), caso contrário o espaço não seria suficiente para que todos os dados ficassem armazenados dentro da página. Caso tivéssemos 2016 registros na nossa tabela do tipo INT, uma página não comportaria todos os dados, dessa forma seria necessário realizar uma divisão de páginas. Neste caso, a página que alocava todos os dados inicialmente (Nível Raiz), será deslocada para o nível folha, sendo que seria necessária uma outra página no nível folha para que metade dos dados da primeira página se “transportasse” para outra (Assim dessa maneira cada página possuiria 1.023 linhas, m o que não ultrapassaria os 8.060 bytes por folha). Também seria necessário alocar mais uma página no nível Raiz de maneira que o nível raiz contivesse os primeiros registros do nível folha (No caso, dois).

Observe que em nenhum momento eu mencionei o nível intermediário. Uma página de nível intermediário só seria criada se, no nível Raiz existem 2016 registros e a página de nível Raiz precisasse sofrer divisão de páginas.

Entendido o funcionamento básico do B-Tree e os conceitos de divisão de páginas e nível raiz, intermediário e nível folha, voltemos à figura. No caso, a figura possui os três níveis (Raiz, intermediário e Folha) Caso eu quisesse localizar o número 1056 na minha tabela, o SQL percorreria o nível raiz e verificaria que o número 1056 está entre os números 1000 e 1500, então ele percorreria apenas a página que contém valores de 1000 a 1500. No nível intermediário ele verificaria que o número 1056 está entre os números 1000 e 1250 então ele percorreria a página no nível folha que iniciasse por 1000 e localizaria o registro.

No outro post, falarei sobre os tipos de índice no SQL.


terça-feira, 17 de agosto de 2010

Arquivos e Grupos de Arquivos


Arquivos:

Dentro do SQL existem três tipos de arquivos:

  • Arquivos com a extensão .mdf
  • Arquivos com a extensão .ndf
  • Arquivos com a extensão .ldf

Tais extensões não são imutáveis, de forma que é possível alterar a extensão dos arquivos, mas por padronização indica-se que se mantenham tais extensões.

A extensão .mdf e .ndf dedicam-se ao armazenamento de dados, sendo uma primária e a outra secundária. Já a extensão .ldf refere-se ao armazenamento de arquivos de log.

Ao criar um arquivo é possível definir a propriedade Filegrowth, e a propriedade Max size. A opção Filegrowth faz com que o arquivo cresça de acordo com o definido no Filegrowth. Pode-se especificar o crescimento em Mg, GB, Tb ou em porcentagem. Dessa forma quando um arquivo criado alcança o tamanho definido no começo, a opção FIlegrowth é usada. Por outro lado a opção Maxsize, como o próprio nome indica, indica um tamanho máximo para tal arquivo, de forma que o Filegrowth não consiga mais atuar naquele arquivo.

FileGroup:

O conceito de FileGroup foi introduzido no SQL para servir como uma camada de abstração para os “usuários”.O Objetivo do Filegroup é “esconder” o armazenamento físico no Sistema Operacional, de forma que quando um DBA por exemplo utilizar o SQL ele não se preocupe e perca tempo definido, ou procurando os arquivos dentro do SO.

Os FileGroup são dividos em três tipos.

· O FileGroup de Dados: Normalmente são os mais utilizados e armazenam textos.

· O fileGroup de Full-Text: Armazenam principalmente índices Full-Text.

· O FileGroup de FileStream.: Armazenam objetos do tipo FileStream.

Ao criar um objeto, deve-se especificar em qual FileGroup esse objeto ficará armazenado. A função da cláusula ON é justamente essa: definir em qual FileGroup um objeto será armazenado. Caso não seja definido o Filegroup de armazenamento de um objeto, o SQL o armazenará em um FileGroup denominado Primary. O FileGroup Primary contém todos os objetos criados sem a clausula ON definida.

Dentro do SQL existe também um FileGroup denominado Default. O FileGroup Default contém definições padrões que serão aplicadas automaticamente em FileGroups criados.

Outra característica importante do FileGroup é o algoritmo de preenchimento proporcional. Considere que você tenha diversos Filegroups em seu banco dados, sendo cada um de um tamanho diferente. O Algoritmo de preenchimento Proporcional garante com que todos os FileGroups cresçam ao mesmo tempo de forma proporcional. Por Exemplo: Caso eu tenha um FileGroup de 10Gb e outro de 1Gb, o algoritmo garantirá que a cada dez linhas gravado no primeiro, uma seja gravada no segundo.

Por Dentro:

O Conceito de linhas e páginas no SQL também merece ser citado aqui.

O SQL considera que em uma página seja dividida de tal forma que a página contenha um tamanho de 8kb. Os primeiros 96 bytes do cabeçalho da página armazenam informações do sistema, como por exemplo: O número da Página, o Tipo da página, a quantidade de espaço livre na página e o ID da unidade de alocação da página. O tamanho restante é usado para guardar dados. Em uma linha pode haver ate 8k de dados. Caso ocorra o estouro de linha,ou seja, a linha não consiga armazenar todas as informações especificadas, o SQL coloca um ponteiro na página e continua gravando os dados no ROW_OVERFLOW_DATA. Caso o espaço seja liberado na linha cheia o SQL remove os dados contidos no ROW_OVERFLOW_DATA e através do IN_ROW_DATA armazena na linha de origem.