A quantidade de linhas fala por si só ?

Bom Dia Pessoal,

Há alguns dias atrás passei uma tarde em minha cadeira monitorando o ambiente e logo ali ao lado estavam reunidos alguns amigos DBAs, analistas de negócio e a área usuária trabalhando na migração de uma aplicação para um ambiente mais parrudo que o atualmente utilizado. Além das pessoas envolvidas, estava na outra ponta da linha do telefone o fornecedor do software. Durante toda essa iteração escutei várias vezes frases do tipo "tem mais de sete milhões de linhas", "a quantidade de linhas é muito grande", etc.

É impressionante como existem muitas argumentações de carga baseadas puramente na quantidade de linhas. Quantas vezes uma software house não usa a quantidade de linhas como robustez da sua solução ("Meu Software processa mais de um milhão de linhas por dia") ? Quantas vezes um fornecedor não recomenda um servidor mais parrudo para processar muitos registros ("Veja bem, recomendo o servidor XPTO com 103 processadores e 105 GB de RAM, pois, serão mais de 1.000 linhas por segundo") ? Ou ainda decisões precipitadas como "A tabela tem dois milhões de registros. É melhor a gente particioná-la para obter desempenho".

Será mesmo que o número de linhas é uma boa métrica para carga, volume e dimensionamento ? Será que podemos dizer que a solução A é melhor que a solução B apenas porque A trabalha com mais linhas que B ? O número de linhas é um indicador importante com certeza, mas não pode ser utilizado isoladamente da forma como muitos utilizam, pois, pode levar a interpretações equivocadas.

Uma metáfora em relação ao mundo cotidiano

Em uma situação hipotética, um casal possui um casa em um grande terreno e está interessado em adquirir uma piscina. Algumas tendências como aquecimento global, trabalho home office e os três filhos pequenos que pedem para ir ao clube todos os dias fizeram com que essa decisão fosse "acelerada" e eles precisam decidir rapidamente.

Uma dos maiores problemas para quem tem piscina em casa refere-se à manutenção. A limpeza da piscina, por exemplo, pode demandar esvaziá-la e posteriormente enchê-la renovando a água "suja" para uma mais "limpa". Como água é um bem que está se tornando cada vez mais escasso e a conta de água é progressiva (quanto mais água se consome, mais se paga e essa relação não é proporcional, pois, a taxa é crescente com o volume) é imprescindível escolher a piscina que ofereça o lazer necessário, mas com a maior economia de água possível.

O casal vai à casa de piscinas mais especializada da cidade e o vendedor dá as seguintes opções:

  • A piscina de 1,5m de profundidade custa R$ 8.000,00
  • A piscina de 2,0m de profundidade custa R$ 12.000,00
  • A piscina de 2,5m de profundidade custa R$ 16.000,00

Normalmente uma piscina com 1,5m de profundidade está muito adequada para lazer e prática da natação. Considerando que as crianças são pequenas, ter uma piscina com 2,0m ou 2,5m de profundidade é até desaconselhável. Vale a pena lembrar que o principal parâmetro para decisão da compra é a quantidade de água (tem que ser a menor possível).

O raciocínio é bem simples. À medida que a piscina se torna mais funda, mais água será necessária para enchê-la. Então a piscina mais econômica será aquela que tem a menor profundidade. Logo a piscina de 1,5m deve ser a escolhida. Pensando assim, o casal optou pela piscina de 1,5m. Como todo cliente inteligente, antes de fechar a compra, o casal pediu para visualizar as piscinas. O esqueleto das mesmas é parecido com a figura abaixo:

De acordo com o raciocínio anterior, a piscina de menor profundidade deveria ser a que mais economizaria, pois a piscina mais raza é a que gasta menos água. Esse raciocínio parece correto, mas é logicamente inconsistente. Primeiro porque a quantidade de água é calculada em função do volume e não da profundidade. Embora a profundidade faça parte do cálculo do volume (Comprimento * Altura * Largura), ela sozinha não determinará o maior volume, pois, existem outros componentes envolvidos no cálculo.

Quando elaborei a figura coloquei todas com o mesmo comprimento variando apenas a largura e a profundidade. A piscina de profundidade 1,5m possui 6x de largura, a de 2,0m possui 3x de largura e de 2,5m possui 2x de largura. Como todas tem o mesmo comprimento vejamos o cálculo do volume para as piscinas

  Comprimento Largura Altura Volume
Piscina 1 c 6x 1,5m 9cx
Piscina 2 c 3x 2,0m 6cx
Piscina 3 c 2x 2,5m 5cx

As medidas de volume mostram que a piscina de 1,5m que possui a menor profundidade ocupa 50% a mais no volume de água em relação à piscina de profundidade de 2,0m e quase o dobro em relação à piscina de 2,5m de profundidade. A regra da profundidade mostrou-se completamente falsa já que possui um raciocínio inconsistente e levaria uma decisão equivocada. Isso porque a medida a ser analisada é o volume de água e não a profundidade (altura) da piscina em questão. A profundidade até poderia definir a piscina que possui o maior volume de água mas isso só seria verdade se as proporções entre comprimento e altura fossem as mesmas para as três piscinas o que não necessariamente é verdade (nesse caso não foi).

Aplicação em banco de dados

E o que o exemplo das piscinas tem a ver com banco de dados ? Se formos pensar nos bancos de dados relacionais e suas tabelas, não teremos propriamente uma figura em três dimensões como uma piscina, mas para cada tabela haverá um plano bidimensional representado por linhas e colunas. O tamanho de uma tabela irá variar diretamente em função dessas duas dimensões, ou seja, quanto maior forem o número de linhas e o número de colunas maior será o tamanho da tabela.

É importante notar que o tamanho das tabelas normalmente é uma medida de grandeza muito melhor que a quantidade de linhas. Embora a quantidade de linhas seja um componente importante para calcular o tamanho da tabela, o tamanho das colunas é igualmente importante e comumente desprezado (quase ninguém pergunta quantas colunas existem na tabela, mas é muito comum perguntar o quantidade de linhas). Embora normalmente a tabela que tem a maior quantidade de linhas seja mais volumosa que a tabela que tem menos quantidade de linhas, isso não é uma verdade absoluta. O exemplo a seguir (SQL Server 2008), mostra uma situação em que isso não acontece:

— Cria uma tabela de Controle Orçamentário
CREATE TABLE ResumoConsolidado (
    Ano SMALLINT, CentroCusto CHAR(5),
    JanPlanejado MONEY, JanExecutado MONEY, JanRealizado MONEY,
    FevPlanejado MONEY, FevExecutado MONEY, FevRealizado MONEY,
    MarPlanejado MONEY, MarExecutado MONEY, MarRealizado MONEY,
    AbrPlanejado MONEY, AbrExecutado MONEY, AbrRealizado MONEY,
    MaiPlanejado MONEY, MaiExecutado MONEY, MaiRealizado MONEY,
    JunPlanejado MONEY, JunExecutado MONEY, JunRealizado MONEY,
    JulPlanejado MONEY, JulExecutado MONEY, JulRealizado MONEY,
    AgoPlanejado MONEY, AgoExecutado MONEY, AgoRealizado MONEY,
    SetPlanejado MONEY, SetExecutado MONEY, SetRealizado MONEY,
    OutPlanejado MONEY, OutExecutado MONEY, OutRealizado MONEY,
    NovPlanejado MONEY, NovExecutado MONEY, NovRealizado MONEY,
    DezPlanejado MONEY, DezExecutado MONEY, DezRealizado MONEY)

— Cria uma tabela de Lancamentos Contábeis
CREATE TABLE Lancamentos (
    IDLancamento INT IDENTITY(1,1),
    DataLancamento DATE,
    ValorLancamento MONEY,
    CentroCusto CHAR(5))

— Insere 1 milhão de resumos consolidados
INSERT INTO ResumoConsolidado VALUES (2009,‘MARKT’,
    150000000,120000000,100000000,
    150000000,120000000,100000000,
    150000000,120000000,100000000,
    150000000,120000000,100000000,
    150000000,120000000,100000000,
    150000000,120000000,100000000,
    150000000,120000000,100000000,
    150000000,120000000,100000000,
    150000000,120000000,100000000,
    150000000,120000000,100000000,
    150000000,120000000,100000000,
    150000000,120000000,100000000)
GO 1000000

— Insere 10 milhões de lançamentos
INSERT INTO Lancamentos VALUES (‘20091220’,1256.12,‘MARKT’)
GO 10000000

Após a execução do script temos uma tabela ResumoConsolidado com 1 milhão de registros e uma tabela de Lançamentos com 10 milhões de registros. Se formos seguir a "falsa" lógica, certamente a tabela de lançamentos é muito mais volumosa, pois, tem 10 milhões de registros contra apenas 1 milhão da tabela de lançamentos. Vejamos então o que o SQL Server nos revela sobre a volumetria dessas tabelas através do script abaixo:

EXEC sp_spaceused @objname = ‘ResumoConsolidado’, @updateusage = ‘true’
EXEC sp_spaceused @objname = ‘Lancamentos’, @updateusage = ‘true’

Após aproximadamente 50 minutos, o resultado das stored procedures é mostrado na tabela abaixo:

name rows reserved data index_size unused
ResumoConsolidado 1000000 320072 KB 320000 KB 8 KB 64 KB
Lancamentos 10000000 300808 KB 300752 KB 8 KB 48 KB

A primeira conclusão é que número de linhas não significa necessariamente muito espaço. A tabela Lancamentos possui 10 milhões de linhas e ocupa apenas 300MB. Com a quantidade de memória dos servidores atuais beirando as dezenas de GB, uma tabela de 300MB caberia em memória sem maiores dificuldades se fosse necessário (isso considerando a completa ausência de índices para facilitar o acesso). A segunda conclusão (e mais importante) é que ao contrário do que se pensava, a tabela com a maior quantidade de linhas não necessariamente é a mais volumosa. A tabela ResumoConsolidado possui 1 milhão de linhas e ocupa 320MB enquanto que a tabela Lancamentos possui dez vezes mais a quantidade de linhas e ainda ocupa menos espaço ficando em 300MB. Assim como a profundidade da piscina, a quantidade de linhas se analisada isoladamente pode levar à raciocínios e decisões equivocadas. A explicação é bem simples. Embora a tabela ResumoConsolidado tenha a menor quantidade de linhas, o tamanho de cada linha é significativamente maior. Para 320MB e 1 milhão de linhas teremos cerca de 320bytes por linha. No caso da Lancamentos, o tamanho da linha fica em torno de 30bytes (300MB / 10.000.000 de linhas). Se fóssemos representar as tabelas em forma bidimensional (linhas x colunas) teríamos as seguintes "áreas".

Se formos considerar que um retângulo possui a altura de 1 milhão de linhas e a largura de 30bytes, para a tabela ResumoConsolidado seria necessário um pouco mais que dez retângulos colocados horizontalmente. Como cada retângulo possui 30bytes com dez retângulos conseguimos preencher 300 bytes, mas 2/3 de um retângulo consegue-se os 20 bytes restantes e assim se obtêm os 320 bytes por linha. Multiplicando esses 320 bytes pela altura de 1 milhão de linhas chega-se a área ed 320MB retornada pela sp_spaceused. No caso da tabela Lancamentos, é necessário empilhar dez retângulos. Cada retângulo possui a largura de 30 bytes que é correspondente à largura do registro. Como a altura de cada retângulo é de 1 milhão de registros, é preciso dez retângulos para chegar na marca de 1 milhão de registros.

Com a utilização dos retângulos é fácil fazer as devidas comparações. A tabela ResumoConsolidado utiliza dez retângulos e mais um pedaço de um retângulo (2 / 3) enquanto que a tabela Lancamentos utiliza apenas 10 retângulos. A diferença entre elas é justamente a área vermelha que corresponde a 20MB. Como pode ser percebido, a tabela ResumoConsolidado ocupará mais espaço em relação à tabela Lancamentos ainda que a tabela ResumoConsolidado tenha menos linhas (apenas um retângulo de altura).

A relevância da quantidade de linhas

Se o tamanho de uma tabela depende da quantidade de linhas e da quantidade de colunas, uma vez que o tamanho da linha permaneça mais ou menos homogêneo é possível fazer julgamentos a partir da quantidade de linhas. Se uma tabela A possui uma linha de tamanho de 100 bytes com 25 milhões de linhas e uma tabela B possui uma linha de tamanho 150 btyes, mas apenas 1 milhão de linhas seguramente a primeira tabela é muito mais volumosa. Entretanto, dada as infinitas realidades de negócio e seus modelos de dados jamais poderemos obter um tamanho padrão para o tamanho de linhas e por consequência dificilmente a quantidade de linhas será um bom indicador de volumetria. Salvo casos absurdos como bilhões ou trilhões de linhas (que fatalmente produzem tabelas muito grandes) será sempre necessário "desconfiar" quando surgir o argumento "a tabela possui milhões de linhas".

Como podemos observar, o tamanho da tabela é uma métrica muito mais adequada que a quantidade de linhas. Ainda assim, o tamanho da tabela não é por si só uma medida que diga muita coisa sozinha. Uma base de 10TB pode até impressionar pelo tamanho, mas não significa necessariamente algo crítico ou que mereça uma atenção fora do normal. Se formos considerar os dados "vivos", ou seja, aqueles que são realmente acessados se restrijam a 100GB por exemplo, certamente a importância de 10TB ficará muito reduzida. 10TB significam muito espaço, longas janelas de backup, mas administrar 100GB não tem o mesmo peso que administrar 10TB efetivos.

O que é de fato importante visualizar é que criticidade e grandeza de uma base de dados dependem de vários fatores. Quantidade de acessos simultâneos à base de dados, tamanho das transações, quantidade de tabelas, total de aplicações diferentes que acessam a base são por exemplo fatores que podem dizer muito mais sobre uma determinada base de dados do que meramente "minha base tem mais de 10 milhões de linhas".

Quase todo processo de troubleshooting, consultoria, documentação e afins possivelmente perguntará "qual é a quantidade de linhas" ou algo parecido. É bem fácil e intuitivo. Isso não está errado. Está apenas incompleto. A quantidade de linhas é importante, mas sozinha nunca será relevante. É preciso sempre usar esse dado dentro de um contexto para evitar distorções.

[ ]s,

Gustavo

3 Respostas para “A quantidade de linhas fala por si só ?

  1. Parabéns pelo artigo Gustavo.Muto boa sua didática.

  2. Ótimo artigo, obrigado pelo trabalho de postá-lo. Agora é recomendar tal link para todos os DBA’s da empresa pra usarem o paradigma certo de mensuração.

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s