NOTÍCIAS

voltar
16.03.15

Degradação de Performance com Firebird

firebird_databases

Texto extraído do site da FIREBASE
www.firebase.com.br
Banco de Dados de um Terabyte
por: Carlos H. Cantu

DEGRADAÇÃO DE PERFORMANCE COM FIREBIRD

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

CPU = AMD FX8350
RAM = 16GB
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.

- SOFTWARE UTILIZADO

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

carrega_database

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)

1

9,04

2535

3,65166075

2

10,80

3197

3,45924304

3

13,00

4057

3,281242297

4

15,50

4698

3,378458919

5

17,30

5455

3,24751604

6

19,90

6037

3,375451383

7

21,60

6473

3,417024564

8

24,20

7539

3,287014193

9

26,00

7779

3,422547885

10

28,60

8851

3,308823862

11

30,30

9266

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).

 - PERFORMANCE

perf4_Firebird_SATA_RAID_performanceO 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)

1

9,04

494,73

2

10,80

491,94

3

13,00

480,36

4

15,50

469,11

5

17,30

446,42

6

19,90

431,61

7

21,60

426,85

8

24,20

424,5

9

26,00

414,04

10

28,60

409,14

11

30,30

407,97

 

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

perf5_firebird_database_size_18tbPara responder a pergunta anterior, decidimos realizar um teste com uma base de 1.77 Terabytes, no mesmo hardware, com a mesma configuração.

- PROCESSO DE CARREGAMENTO DOS DADOS

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

566448

3,279214122

 

- PERFORMANCE DO BANCO DE 1,77 TERABYTE

perf7_performance_with 1800Gb_Firebird_databaseApó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.

 

#

Tamanho do BD (GB)

Performance (SATA RAID1)

1

9,04

494,73

2

10,80

491,94

3

13,00

480,36

4

15,50

469,11

5

17,30

446,42

6

19,90

431,61

7

21,60

426,85

8

24,20

424,5

9

26,00

414,04

10

28,60

409,14

11

30,30

407,97

12

1813,969025

169,33

 

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

perf10_SSD_SATA_load_speedFoi 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.

 

- PERFORMANCE

perf11_SSD_vs_SATA_performance_FirebirdComo 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.

 

- CONCLUSÃO DOS TESTES

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

- TABELAS

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 %
ORDER_LINE 6300024797 60.09 38880344 607505.3 50582.3 34
STOCK 2100000000 298.88 43783806 684121.9 15809.61 39
ORDERS 630004141 29.00 2692324 42067.56 4250.38 2
HISTORY 630000434 48.77 3446455 53850.86 0.00 3
CUSTOMER 630000000 577.52 24226054 378532.0 8675.78 21
NEW_ORDER 188999981 13.00 623764 9746.31 1260.84 1
DISTRICT 210000 103.92 1860 29.06 1.27 ~0
ITEM 100000 82.73 756 11.81 0.52 ~0
WAREHOUSE 21000 97.90 179 2.80 0.11 ~0

 

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.

- ÍNDICES

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
ORDER_LINE_PK ORDER_LINE 4 6300024797 1.41 6300024797 50582.34
STOCK_PK STOCK 4 2100000000 1.00 2100000000 15809.61
ORDERS_PK ORDERS 3 630004141 1.01 630004141 4250.38
CUSTOMER_LAST CUSTOMER 3 630000000 0.00 1000 4029.64
CUSTOMER_PK CUSTOMER 3 630000000 1.01 630000000 4646.14
NEW_ORDER_PK NEW_ORDER 3 188999981 1.01 188999981 1260.84
DISTRICT_PK DISTRICT 2 210000 1.37 210000 1.27
ITEM_PK ITEM 2 100000 1.00 100000 0.52
WAREHOUSE_PK WAREHOUSE 2 21000 1.00 21000 0.11

 

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.

- AQUECIMENTO

heatingAntes 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 ORDER_LINE;
select first 1 * from STOCK;
select first 1 * from customer;
select first 1 * from ORDERS;
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)).

 - QUERIES

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
Current memory = 166919744
Delta memory = 5616
Max memory = 166977488
Elapsed time= 0.08 sec
Buffers = 10000
Reads = 1
Writes 0
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
select count(*)
from WAREHOUSE,  customer
where c_w_id = w_id and c_w_id = 10000
PLAN JOIN (WAREHOUSE INDEX (WAREHOUSE_PK), CUSTOMER INDEX (CUSTOMER_PK))COUNT
============
30000STATISTICS
Current memory = 166918560
Delta memory = -1184
Max memory = 166977488
Elapsed time= 0.16 sec
Buffers = 10000
Reads = 1175
Writes 0
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
Current memory = 167013640
Delta memory = 95080
Max memory = 167055968
Elapsed time= 0.80 sec
Buffers = 10000
Reads = 10285
Writes 0
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
Current memory = 167125464
Delta memory = -7160
Max memory = 167267976
Elapsed time= 3.41 sec
Buffers = 10000
Reads = 1994
Writes 0
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.
Select first 10 w_id, w_name, c_id, c_last
from WAREHOUSE,  CUSTOMER
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
Current memory = 167687664
Delta memory = -651888
Max memory = 168931400
Elapsed time= 0.19 sec
Buffers = 10000
Reads = 31
Writes 0
Fetches = 63
Query com join e duas condições.
select first 10
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
from customer c1
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)
join Item i1 on (ol1.OL_I_ID = i1.i_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
Current memory = 166807128
Delta memory = 6016
Max memory = 166879200
Elapsed time= 0.20 sec
Buffers = 9999
Reads = 1
Writes 0
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.

 

- CONCLUSÃO DOS TESTES

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.

VEJA TAMBÉM

  • 17.01.18

    Parceria Soluvert e JB Software

    Convencao

    Consolidando a parceria técnica e comercial com a JB Software, a Soluvert esteve presente na 12º convenção anual de franquias.

    + ler tudo
  • 27.12.17

    Manutenção de Equipamentos Hospitalares

    2017-12-27 (7)

    A Manutenção preventiva é a ação de controle e monitoramento dos equipamentos, com o objetivo de reduzir ou impedir falhas em seu desempenho.

    + ler tudo
  • 08.12.17

    Preceptoria na residência médica

    2017-12-08 (2)

    Você sabe qual é o papel do Preceptor na residência médica ?

    + ler tudo