Muitos usuários alegam que suas aplicações de bases de dados começam a ter problemas de performance quando a base atinge um determinado limiar: pode ser 3, 5, 10 Gb e etc.
Home > Notícias > Degradação de Performance com Firebird
Degradação de Performance com Firebird
Texto extraído do site da FIREBASE
Banco de Dados de um Terabyte
por: Carlos H. Cantu
Uma das preocupações mais importantes em relação a bancos de dados é a degradação de performance. Muitos usuários alegam que suas aplicações de bases de dados começam a ter problemas de performance quando a base atinge um determinado limiar: pode ser 3Gb, 5Gb, tamanho da memória RAM, 20Gb, etc. A queixa mais comum é quando o tamanho da base ultrapassa a quantidade de RAM disponível no servidor. Será verdade?
Vamos realizar uma série de testes para checar se há realmente degradação de performance relacionada com o crescimento da base de dados. Para tanto, simulamos o crescimento da base de dados com a mesma carga e o mesmo hardware, realizando 11 testes com bases de dados entre 9GB e 30GB.
- HARDWARE UTILIZADO
HD (database) = RAID 2 x 4 TB, SATA, Segate
Como se pode ver, é uma máquina com configuração modesta, podendo ser considerado um servidor típico de baixo custo, talvez exceto pelos drives SATA de alta capacidade, mas de acordo com o fabricante, drives de 1TB e 4TB tem praticamente a mesma velocidade.
Sistema Operacional = Windows Server 2008R2 (64 bits).
Firebird = Firebird SuperServer 64bits
Loader = Custom loader from tpc-based test
Como o objetivo do teste é medir a variação de performance de um sistema tradicional, nós usamos o Firebird SuperServer 64bits, e não o Classic, para simular o cenário mais comum em pequenas empresas, que geralmente usa o que foi instalado há anos. Como você deve saber, o SuperServer, por padrão, usa apenas uma CPU/Core, portanto, provavelmente o Classic/SuperClassic (que usa todos os processadores) poderia mostrar resultados melhores, mas o objetivo do teste não é ajuste de performance.
- CONFIGURAÇÃO DO ARQUIVO DE BANCO DE DADOS E DO FIREBIRD (SGBD)
Alteramos dois parâmetros do firebird.conf, conforme sempre recomendamos aos nosso usuários: aumentamos o page buffers para 10.000 e o espaço temporário para sort. Todas as bases de dados utilizadas foram criadas com page size de 16.384 bytes.
- PROCESSO DE CARREGAMENTO DOS DADOS
Cada teste era composto de duas etapas: carga e simulação de 20 terminais que realizavam inserts, updates e deletes. A carga dos dados foi executada pela aplicação load.exe, que insere dados em diversas tabelas. Como se vê na figura abaixo (linha vermelha), a velocidade de inserção dos dados variou entre 35 MB/seg a 1 MB/seg.
A diferença de velocidade é devida ao próprio design da aplicação de carga, e não ao Firebird: o loader foi desenhado de forma que insira rapidamente 70% dos dados desejados, e lentamente insera o restante das informações. Esse comportamento foi repetido nos testes com todas as bases de dados, pois é importante executar exatamente as mesmas operações em todos os testes, para que possamos fazer a média de velocidade de carga.
É importante mencionar que o loader.exe insere apenas dados, sendo que os índices são criados após a carga estar completa.
Abaixo temos a tabela com os valores obtidos com a carga nos 11 bancos de dados com tamanhos variando entre 9GB e 30GB.
Tamanho da base (GB)
Tempo de carga (seg)
Velocidade de carga (MB/seg)
3,65166075
3,45924304
3,281242297
3,378458919
3,24751604
3,375451383
3,417024564
3,287014193
3,422547885
3,308823862
3,348499892
Como podemos ver, os dados são relativamente estáveis, e a media de variação da velocidade de carga variou entre 3.3-3.4MB/sec. Não há sinais que a performance caia quando a base de dados passa a quantidade de RAM disponível (após a base #5, com 17.3GB).
O tempo de carga foi bastante promissor, mas e quanto aos resultados de performance? Antes de comentar, vamos rever rapidamente o processo de simulação.
A simulação roda 20 threads, e cada uma delas realiza diversas operações de negócio: cria pedidos, processa pagamentos, faz contagem de estoque, processa o envio dos pedidos, etc. Como você pode perceber, simulamos um ambiente normal de uma aplicação de vendas.
A aplicação de teste mede o número de operações de negócio por segundo, e reporta a média. Obviamente, esse número é um parâmetro artificial, mas é bom o suficiente para comparação.
Tamanho do BD (GB)
Performance (SATA RAID1)
Como se pode observar, existe uma lenta degradação de performance conforme o tamanho da base aumenta – quanto maior a base de dados, mais lenta será (no mesmo hardware). Não há grande degradação de performance quando a base de dados ultrapassa a quantidade de RAM. O crescimento da base de dados de 9GB para 30GB leva praticamente a 20% de perda de performance.
Bases de dados Firebird com 30GB atualmente são facilmente encontradas pelo mundo afora, e continuam crescendo com o passar do tempo.
E o que acontecerá com a performance do banco, quando a base se tornar maior? Ou melhor, MUITO MAIOR!
- BANCO DE DADOS 1.77 TERABYTES
Para responder a pergunta anterior, decidimos realizar um teste com uma base de 1.77 Terabytes, no mesmo hardware, com a mesma configuração.
A carga durou 566.448 segundos – 157 horas, 6.55 dias. É muito tempo, mas a media de velocidade de carga foi de 3.28MB/seg
Tamanho da base, Gb
Tempo de carga, seg
Velocidade de carga, MB/seg
1813,969025
3,279214122
- PERFORMANCE DO BANCO DE 1,77 TERABYTE
Após a carga, realizamos novamente o teste de performance, dessa vez com a base de 1.77TB.
O resultado confirma que há uma lenta e estável queda de performance no Firebird – enquanto a base de dados cresceu 60 vezes (de 30GB para 1.7713GB), a queda de performance foi de 2.4 vezes (de 407 para 169 pontos).
Não é comum que uma base de dados cresça tanto sem que se melhore o hardware do servidor, mas mesmo nessa situação, o Firebird continua funcionando.
Após completar a série de testes com um hardware de baixo custo, decidimos checar como seria o resultado usando outro tipo de tecnologia de armazenamento, e instalamos um drive SSD no mesmo servidor.
- TESTANDO O BANCO DE DADOS DE 1,77 TERABYTES COM DRIVES SSD
Foi instalado um drive Plextor PX-256M M5 Pro, e executados a mesma série de testes (com exceção da base de 1.77TB), com as mesmas configurações.
Os resultados foram adicionados no gráfico comparativo com os dispositivos SATA, conforme figura ao lado.
O tempo de carga no drive SSD é praticamente o mesmo do SATA. Isso é esperado, pois a velocidade de escrita sequencial é praticamente a mesma entre drives SATA e SSD.
Como podemos observar, a performance com operações de I/O randômicas mostra uma performance 8x melhor para o drive SSD. Nossa experiência com clientes mostra que drives SSD são de 30 a 50% mais rápidos no uso de aplicações reais, mas um ganho de 8x é tremendamente alto.
No entanto, esse teste é artificial e especialmente desenhado para simular uma alta carga de operações de OLTP, com muitos updates e deletes, mas sem grandes recuperações de informação. As aplicações de bases de dados mais comuns não trabalham dessa forma todo o tempo. Isso explica porque o SSD mostra um resultado tão bom nesse caso específico.
Primeiro – a performance do Firebird não apresenta queda acentuada relacionada a alguma restrição de tamanho. No mesmo hardware, a performance terá uma degradação lenta com o crescimento da base de dados. Essa degradação pode ser compensada com o tuning da configuração do Firebird ou com um upgrade inteligente de hardware.
Segundo – comprovamos que mesmo bases de dados gigantes (1.7TB) funcionarão em um hardware de baixo custo, com uma queda de performance significativa mas ainda aceitável.
Terceiro – SSD é muito bom para uso com aplicações OLTP. Provavelmente, é a opção de menor custo para aumentar a performance no momento. Obviamente, usar um SSD não resolverá os problemas relativos à queries com planos de acesso ruins e índices ineficientes, mas pode aumentar a performance de forma geral.
- DETALHAMENTO DOS TESTES
Na tabela abaixo listamos as tabelas da base de dados com suas principais características. Os dados foram obtidos com o gstat -a -r e interpretados pelo IBAnalyst.
Tabela Records RecLength, bytes Data Pages Table size, Mb Indices size, Mb Total %
Como podemos observar, a maior tabela é a ORDER_LINE – contendo mais de 6 bilhões de registros. Seu tamanho é de cerca de 600Gb sendo que 50GB são ocupados por índices. Ela ocupa 34% do tamanho total da base de dados.
A tabela STOCK também é imensa – cerca de 2 bilhões de registros. Apesar do número de registros ser menor do que a tabela ORDER_LINE, a STOCK ocupa ~680Gb na base de dados (39%), pelo fato do comprimento dos registros na tabela STOCK ser 298.88 bytes contra apenas 60.09 bytes na ORDER_LINE. Da mesma forma, o tamanho dos índices associados a tabela STOCK é de apenas 15Gb.
A terceira maior tabela, CUSTOMER, tem um comprimento de registro ainda maior – 577.52 bytes, e ocupa 378Gb (21%) com apenas 630 milhões de registros.
Existem poucos índices nessa base de dados, pois foi modelada apenas para testes – a maioria das tabelas tem apenas um índice – a chave primária. No mundo real, os desenvolvedores criam diversos índices para servir a necessidades especiais, mas aqui, limitamos os índices para nos concentrar na velocidade das inserções e atualizações dos dados – como resultado, o tamanho do índice representa apenas 5-10% do tamanho da tabela, quando geralmente o cenário mais comum é de 30-50% (se mais de 50% do tamanho de uma base de dados é ocupada por índices, considere remodelar a base de dados, ou remover índices desnecessários).
Na tabela abaixo listamos todos os índices da base de dados e suas características:
Index Table Depth Keys # Key Len, bytes # of unique keys Size, Mb
CUSTOMER_PK CUSTOMER 3 630000000 1.01 630000000 4646.14
Todos os índices possuem um tamanho de chave reduzido – a maior é 1.41, significando que o índice tem um índice de compressão bastante efetivo – por exemplo, a o índice primário da tabela ORDER_LINE contém 6 bilhões de chaves em 50Gb de espaço. Um resultado muito bom.
Existem 2 índices com profundidade igual a 4. Isso significa que o Firebird precisa fazer 4 leituras em páginas de índices para encontrar o valor desejado. É recomendado que a profundidade dos índices não seja maior que 3. Se for maior, o tamanho da página da base de dados deve ser aumentado. No entanto, essa base de dados já está com o tamanho de página no limite (16kb), portanto, teremos que viver com isso.
Antes de continuarmos e falarmos de grandes consultas, vamos "aquecer" a base de dados. Quando a base de dados é grande, os dados das tabelas de sistema associadas aos objetos do banco de dados também são grandes, e leva algum tempo para que o Firebird coloque as páginas de sistema no cache. Por exemplo, a tabela ORDER_LINE tem 10.110 páginas de ponteiro. "Aquecimento" é necessário para qualquer base de dados grande.
Com a base "fria", a execução das queries levará muito mais tempo do que com a base "aquecida".
Para aquecer o cache do banco de dados, vamos executar uma série de consultas simples, para ler os dados de sistema para o cache:
select first 1 * from NEW_ORDER;
Isso é suficiente para uma base com modelagem tão simples. Para bases de dados mais complexas, com centenas de tabelas, o "aquecimento" pode ser mais complexo, e precisa ser bem pensado. (Veja na figura ao lado, o consumo de memória do processo do Firebird (Firebird SuperServer 2.5.2 64 bit)).
Após o "aquecimento", vamos executar diversas consultas típicas para simular o uso normal de um sistema. Vejamos o tempo de resposta para essas consultas, e o número de operações de leitura.
Query Plan and stats Description
select first 10 w_id, w_name, c_id, c_last from WAREHOUSE, customer
where c_w_id = w_id and c_w_id = 10000 PLAN JOIN (WAREHOUSE NATURAL, CUSTOMER INDEX (CUSTOMER_PK))STATISTICS
Fetches = 51 Junção da tabela WAREHOUSE (21000 records) com a CUSTOMER (630 million records), com a condição de pegar um armazém específico
where c_w_id = w_id and c_w_id = 10000 PLAN JOIN (WAREHOUSE INDEX (WAREHOUSE_PK), CUSTOMER INDEX (CUSTOMER_PK))COUNT
30000STATISTICS
Fetches = 60040 Contagem de registros para a query anterior.
SELECT first 10 * FROM ORDER_LINE
WHERE OL_W_ID = 10050 PLAN (ORDER_LINE INDEX (ORDER_LINE_PK))STATISTICS
Fetches = 10424 Query na maior tabela da base – ORDER_LINE (~6billion records) com a condição de selecionar os registros de um armazém específico. Como a chave primária ORDER_LINE_PK é composta, e contém a ID do armazém (CONSTRAINT ORDER_LINE_PK:
Primary key (OL_W_ID, OL_D_ID, OL_O_ID, OL_NUMBER), o índice é efetivamente usado nessa consulta.
SELECT count(*) FROM ORDER_LINE WHERE OL_W_ID = 10050; PLAN (ORDER_LINE INDEX (ORDER_LINE_PK))COUNT
299509STATISTICS
Fetches = 599170 Contagem da consulta anterior. A segunda consulta com os mesmos parâmetros sera muito mais rápida, mas queries com parâmetros diferentes apresentam um resultado similar.
where c_w_id = w_id and (c_w_id > 8000) and (c_w_id < 10000) PLAN JOIN (WAREHOUSE INDEX (WAREHOUSE_PK), CUSTOMER INDEX (CUSTOMER_PK))STATISTICS
Fetches = 63 Query com join e duas condições.
c1.C_ID, c1.C_FIRST, c1.C_LAST, o1.O_ID, o1.O_OL_CNT, i1.I_NAME, i1.I_PRICE, ol1.OL_AMOUNT
join orders o1 on (c1.c_w_id = o1.O_w_ID and c1.C_D_ID = o1.O_D_ID and c1.C_ID = o1.O_C_ID)
join ORDER_LINE ol1 on (ol1.ol_w_id = c1.C_W_ID and ol1.OL_D_ID = c1.C_D_ID and ol1.OL_O_ID = o1.O_ID)
where o1.o_d_id = 1 and o1.o_w_id = 1 and c1.c_id = 10; PLAN JOIN (C1 INDEX (CUSTOMER_PK), O1 INDEX (ORDERS_PK), OL1 INDEX (ORDER_LINE_PK), I1 INDEX (ITEM_PK))STATISTICS
Fetches = 4960 Query para mostrar os detalhes de um cliente específico em um armazém e distrito específico. Demonstra a performance de junções mais complexas.
Como podemos ver, a base de dados de 1.7 Terabytes apresenta uma boa performance com o Firebird, para consultas comuns. Se a query for bem desenhada e fizer uso de bons índices, a performance é boa até mesmo em bases de dados imensas. É claro, há pontos críticos, como o tempo de fetch para datasets muito grandes e longo tempo para operações de count (pelo fato do Firebird visitar todas as páginas para obter o número exato de registros para aquela query naquela transação especifica), mas esses pontos críticos são bem conhecidos pelos desenvolvedores mais experientes, e há métodos de se modelar a base de dados para contorna-los.