23 altri modi per velocizzare Firebird
Alexey Kovyazin, IBSurgeon, [email protected], 08-gen-2019
Traduzioni: Portoghese
Perché “altri 23”?
Alcuni di voi ricorderanno l’articolo « 45 modi per velocizzare Firebird», pubblicato a maggio 2016. Ora è il momento di pubblicare la prossima serie di suggerimenti e trucchi, basati principalmente sull’esperienza di ottimizzazione e manutenzione di database e server Firebird con un numero elevato di connessioni (1000+).
1. Impostare le Opzioni Risparmio Energia su Prestazioni Elevate in Windows Server 2016 e 2019
Per impostazione predefinita, Windows Server ha un piano di alimentazione impostato su “Bilanciato”, che non è adatto ai server di database. Impostatelo su “Prestazioni elevate” e otterrete circa +20% di prestazioni per le operazioni intensive di CPU. Può essere impostato online, senza riavvio o reboot. L’immagine sottostante mostra il grafico della CPU, che dimostra il vantaggio del piano di alimentazione “Prestazioni elevate”:

Maggiori dettagli sui nostri test con i piani di alimentazione di Windows si possono trovare qui.
2. Abilitare «Interagisci con il desktop» su Classic per Windows
Se state usando Firebird con architettura Classic su Windows, abilitate la casella «Consenti al servizio di interagire con il desktop». Senza questa impostazione, la risorsa «desktop heap» è limitata da Windows, e Firebird non può aprire più di 250-300 connessioni (dipende dai metadati del database e dal relativo consumo di memoria) - si verificherà un errore Out Of Memory.

3. Attenzione: Domain Controller
Il problema è che Windows con ruolo Domain Controller disabilita la cache di scrittura sul disco con il database di Active Directory.
Ciò influisce su Firebird in vari modi (così come su altre applicazioni, naturalmente), e mostra prestazioni significativamente peggiori rispetto ai server senza ruoli di Active Directory.
Si prega di notare che questo problema riguarda versioni di Windows molto diffuse come Windows Small Business Server 2011, così come altre versioni con DC.
4. Aumentare il limite «max open files» su Linux
Se state usando Linux come server di database, non dimenticate di ottimizzare i limiti per Firebird. Controllate i limiti per il vostro processo Firebird (SuperServer o SuperClassic) con il seguente comando:
cat /proc//limits
e prestate attenzione alla riga con il numero massimo di file aperti.
Firebird può usare fino a 4 handle per connessione, e se avete qualcosa come questo:
Max open files 4096 4096 files
significa che il numero totale di connessioni servite dal processo Firebird sarà limitato a circa 1000.
Si prega di notare - se avete 4 database sul server, la connessione per ogni database viene conteggiata.
Impostate un valore più alto - raccomando 65535.
Non dimenticate di controllare di nuovo dopo il riavvio del processo Firebird: è stato applicato o no.
Per l’architettura Classic, è necessario controllare e aumentare i limiti per l’utente «firebird».
5. Usare Linux moderno
Sì, capisco che questo consiglio sia banale, ma ho visto molte volte un buon miglioramento delle prestazioni dopo la migrazione da CentOS 6 a 7, da Ubuntu 12 a 16 (sullo stesso hardware!), quindi ora è la raccomandazione indispensabile per i server di database con più di 250-300 connessioni. Il Linux moderno è un prerequisito prima di ulteriori passi di ottimizzazione.
Versioni raccomandate di Linux: CentOS 7.x e Ubuntu 16, 18.
6. Riservare il 40% della RAM per la cache dei file su Windows
Il Memory Manager del sistema operativo ha implicazioni riguardo all’allocazione della memoria e, per impostazione predefinita, Windows richiede il 40% della RAM per la cache dei file.
Sfortunatamente, il misero strumento Windows Task Manager mostra la memoria usata per la cache dei file come «libera», e alcuni amministratori cercano di far consumare a Firebird tutta questa memoria libera, impostando il parametro DefaultDBCachePage in firebird.conf a valori molto alti, e questo di solito porta allo swapping.
Usate sempre lo strumento RAMMap per vedere l’utilizzo effettivo della memoria su Windows.
La regola empirica per Windows Server (dedicato all’uso come server Firebird) è la seguente: la memoria di Firebird (Working Set) dovrebbe essere inferiore al 40% della RAM totale. Se la dimensione totale dei working set per tutti i processi è superiore al 50%, Windows può avviare lo swap.
Si prega di notare: “riservare” qui significa non solo “non impostare troppi page buffer in Firebird” ma, altrettanto importante, limitare l’uso della memoria da parte di altri software. Ad esempio, se avete MS Exchange o MSSQL sullo stesso server con Firebird, assicuratevi di limitare il loro appetito di memoria.
Se siete interessati a conoscere i dettagli, ho registrato il webinar dedicato alla gestione della memoria in Firebird:
- Parte 1. https://www.youtube.com/watch?v=ZBmLgbYt4aM
- Parte 2, https://www.youtube.com/watch?v=-1.DF2FnU-A
7. Riservare il 30% della RAM per la cache dei file su Linux
Linux lavora con la cache dei file in modo diverso rispetto a Windows e, in generale, la quantità di RAM usata per la cache dei file può essere significativamente inferiore rispetto a Windows, senza un degrado evidente delle prestazioni di Firebird. Tuttavia, per garantire alte prestazioni del sistema con un numero elevato di connessioni, specialmente su Classic e SuperClassic, una buona idea sarà riservare il 30% della RAM per la cache dei file.
8. Usare irqbalance su Linux
irqblalnce spesso migliora le prestazioni di Firebird e il bilanciamento del carico della CPU sui server con un numero elevato di core.
9. Per le Macchine Virtuali - attenzione al Memory Overcommit
Una Macchina Virtuale può essere configurata per avere più memoria di quella fisicamente esistente sulla macchina host - con una funzionalità nota come Memory Overcommit (il nome può essere diverso nei diversi sistemi di virtualizzazione). Ciò significa che in caso di picco di consumo di memoria (sulla VM con il server di database o sulla VM vicina) può iniziare lo swap, il che porterà a ritardi significativi. Per una VM ad alte prestazioni destinata a un server di database, tutta la memoria dovrebbe essere statica.
10. Per le Macchine Virtuali - controllare i limiti della VM
Spesso le VM vengono create con limiti predefiniti di CPU e IO, che possono essere molto bassi, come 50 IOPS e 10% di CPU. Controllate le impostazioni della VM del vostro server e rimuovete qualsiasi limite - un server di database ad alte prestazioni dovrebbe avere tutta la CPU, la larghezza di banda e l’IO possibili.
11. Pulire i file temporanei di Firebird
Firebird crea molti file temporanei per varie operazioni: ordinamento, elaborazione BLOB, tracing. Questi file sono memorizzati nelle seguenti posizioni: su Windows C:\ProgramData\firebird, su Linux / tmp / firebird
Normalmente questi file dovrebbero essere puliti automaticamente, tuttavia, a volte ciò non accade (ad esempio, in caso di riavvio del server).
Controllate periodicamente queste cartelle e pulite i file vecchi - potrebbero esserci molti GB di file obsoleti fb_NNN, e pulirli libererà spazio sull’unità di sistema.
12. Non dimenticate di abilitare la cache dei file con una grande cache di Firebird
Come sapete, la cache di Firebird (chiamata anche «page buffers») è specificata dal parametro DefaultDBCachePages in firebird.conf/databases.conf, o direttamente nell’intestazione del database.
In Firebird 3 SuperServer la dimensione di questa cache può essere impostata molto alta, ma è importante ricordare un altro parametro: FileSystemCacheThreshold.
Se FileSystemCacheThreshold è inferiore a DefaultDBCachePages o ai page buffers, la cache dei file del sistema operativo non sarà utilizzata, il che può portare a problemi di prestazioni.
Nel 99% dei casi, è meglio avere la cache dei file abilitata.
Per garantire ciò, impostate sempre i parametri secondo la seguente regola:
- DefaultDBCachePages = X
- FileSystemCacheThreshold = X+ N, N>1
Ci sono rari casi in cui disabilitare la cache dei file migliora le prestazioni - se avete un esempio del genere, contattatemi - [email protected]!
13. Velocizzare il database di sicurezza
Ogni connessione al database Firebird stabilisce la connessione al database di sicurezza (security3.fdb nel caso di Firebird 3) ed esegue diverse letture e scritture (pagine di transazione, pagina di intestazione). Se avete connessioni frequenti, le prestazioni del vostro database di sicurezza possono diventare un problema.
Come minimo, potete fare quanto segue:
- Aumentare i page buffer per securityN.fdb (l’ottimo empirico è 256 buffer)
- Spostare security3.fdb su un’unità veloce (è una funzionalità standard in Firebird 3, nella 2.5 richiederà una reinstallazione)
Poi, potete impostare Forced Writes OFF per il database di sicurezza - la piccola probabilità di corruzione non è un problema in questo caso.
Il modo più radicale è rendere il database di sicurezza di sola lettura - eliminerà tutte le scritture su di esso.
Se non cambiate spesso gli utenti nel database di sicurezza, è la soluzione migliore.
14. Provate SuperClassic su Firebird 3
In Firebird 3 l’architettura SuperServer è stata ampiamente pubblicizzata come la soluzione definitiva per le prestazioni, ma ci sono alcuni tipi di carico che dimostrano prestazioni migliori con SuperClassic (ma non Classic - funziona sempre più lentamente di SuperServer/SuperClassic).
Come condurre questo esperimento in modo sicuro? Seguite i passi seguenti:
Per provare SuperClassic
- Impostate in firebird.conf
- ServerMode=SuperClassic
- DefaultDbCachePages=1024
- gfix -buff 0
- Riavviate Firebird
Per tornare a SuperServer
- Impostate in firebird.conf
- ServerMode=SuperServer
- DefaultDbCachePages=N # N*page size*databases_count < 25% RAM
- FileSystemCacheThreshold = N+1
- gfix -buff 0
- Riavviate Firebird
Scrivetemi ([email protected]) riguardo ai risultati dell’esperimento, sono interessato a vedere i risultati.
15. Database grande? Aumentate la dimensione della pagina
Per impostazione predefinita, i database Firebird hanno le seguenti dimensioni di pagina:
- 2.5 - 4096 byte
- 3.0 - 8192 byte
Tuttavia, la dimensione massima della pagina è 16K (nella 4.0 - 32K).
Per database superiori a 100Gb nel 95% dei casi, è meglio avere la dimensione di pagina più alta disponibile, al fine di:
- Diminuire la profondità degli indici. Si raccomanda di avere indici con profondità inferiore o uguale a 3. Gli indici con profondità 4 e 5 saranno molto più lenti
- Aumentare l’utilizzo della RAM. La cache di Firebird è specificata in pagine, 1000 pagine con dimensione di pagina 8K saranno 8Mb di memoria effettiva, e con 16K - 16Mb.
- Diminuire il numero di pagine di sistema. Velocizzerà l’accesso ai record delle tabelle grandi (meno salti pointer-pointer-data page), e aiuta con la preparazione delle grandi query SQL. Per aumentare la dimensione della pagina del database, il database deve essere sottoposto a backup con lo strumento gbak e poi ripristinato con il parametro -page ( gbak -c -page 16384).
Si prega di notare: se avete un database con molti piccoli blob, aumentare la dimensione della pagina può sia diminuire che aumentare la frammentazione, ed è difficile prevedere se aumenterà o diminuirà le prestazioni.
16. Non usate il flag no_reserve
Il flag no_reserve fa sì che Firebird non riservi spazio libero (30%) sulle pagine di dati per le possibili versioni dei record, che si verificano dopo UPDATE o DELETE. Questo flag consente di memorizzare i dati in modo più compatto (e anche la dimensione del database è inferiore), ma in caso di UPDATE/DELETE tutte le modifiche vanno alla nuova pagina di dati. Di conseguenza, nel database con il flag no_reserve le operazioni UPDATE/DELETE sono più lente.
Quindi, se il vostro database non è di sola lettura, raccomando di rimuovere il flag no_reserve.
Come verificare se è impostato o no - vedete la riga Attributes nell’output di
gstat -h database
Come disabilitarlo:
gfix -use reserve database
Dopo questo comando, le nuove pagine di dati saranno create con spazio riservato.
Tuttavia, per ottenere l’effetto completo, è necessario eseguire il backup del database con gbak e poi ripristinarlo, in questo caso tutte le pagine di dati saranno con spazio riservato.
Si prega di notare: la dimensione del database crescerà dopo la rimozione del flag no_reserve e il backup/ripristino.
17. Impostare una dimensione iniziale elevata per la tabella dei lock di Firebird
La tabella dei lock è il meccanismo di Firebird, utilizzato per sincronizzare l’accesso agli oggetti interni del motore.
La tabella dei lock di Firebird può crescere automaticamente, ma il suo incremento è un’operazione lenta, che può causare micro-freeze. La tabella dei lock può solo crescere, partendo dalla dimensione iniziale (impostata in firebird.conf).
Per evitare più cicli di incremento della tabella dei lock, una buona idea è monitorare la dimensione della tabella dei lock alla fine del periodo di lavoro (giorno, settimana, ecc.) e poi impostarla come dimensione iniziale in firebird.conf.
LockMemSize=99999999
Per riferimento: LockMemSize su sistemi ad alto carico con ~1000 utenti è solitamente inferiore a 200Mb.
18. Usare fb_lock_print per contare il numero di connessioni al database
Ottenere il numero di connessioni al database è un compito frequente per gli sviluppatori di database: può essere necessario, ad esempio, per scopi di licenza.
Spesso gli sviluppatori usano la query SELECT count(*) FROM MON$ATTACHMENTS per ottenere questo valore, ma non è il modo ottimale: query frequenti alle tabelle MON$ possono essere un peso per il database, quindi è meglio usare l’alternativa:
Eseguire
fb_lock_print -d database_name | alias
e controllare il valore Owners - mostrerà il numero corrente di connessioni al database.
19. Evitare LEFT JOIN non necessari
Spesso vedo query con costruzioni come questa:
T1 LEFT JOIN T2 ON (…) WHERE T2.Field_condition
Essenzialmente, la condizione su T2 esclude i NULL dall’output del LEFT JOIN T2, quindi è possibile cambiare LEFT JOIN in INNER JOIN - non influenzerà il risultato della query.
INNER JOIN dà più libertà all’optimizer di Firebird e, nelle versioni moderne di Firebird, è ottimizzato molto meglio di LEFT.
Ha particolarmente senso nei seguenti casi:
- Nessuna condizione per T1 nella clausola WHERE
- T2 è una tabella piccola
20. Evitare il conteggio non necessario dei record
Un altro errore comune nelle query complesse di database e nelle stored procedure è usare select count() solo per verificare l’esistenza del record.
La seguente query leggerà tutti i record secondo condition1:
(select count(*)…. where condition11) >0
Meglio usare invece questa costruzione
Exists(select first 1 id where condition1)
Se condition1 restituisce più di 1 record, l’opzione proposta sarà molto più veloce, perché non legge tutti i record, si ferma dopo il primo record recuperato.
21. Evitare l’ordinamento non necessario nelle stored procedure
L’ordinamento dei risultati della query all’interno della stored procedure dovrebbe essere giustificato dalla logica di business.
Ad esempio, nell’esempio della stored procedure seguente, la clausola ORDER BY è inutile dal punto di vista della logica di business, ma aggiunge un’operazione di ordinamento non necessaria.
create or alter procedure NEW_PROCEDURE
returns (
SUMX double precision)
as
declare variable _amount double precision;
begin
for select T1.amount from Table1 t1 where ....
order by id
into :_amount
do
begin
sumx=sumx+_amount
end;
suspend;
end
Controlla il tuo codice PSQL per situazioni simili e rimuovi ORDER BY inutili (così come distinct e UNION).
22. Non mantenere le query in stato preparato senza necessità
Spesso vediamo 500-1000 statement preparati in ogni connessione (può essere verificato con le query MON$).
La stragrande maggioranza di essi viene eseguita solo una volta, e poi restano semplicemente nella RAM, rendendo il working set di Firebird più grande e rallentando le query MON$.
La raccomandazione è di mantenere le query SQL in stato preparato solo se sono destinate a essere eseguite molte volte, o se il loro tempo di preparazione è elevato (può accadere per query molto grandi con molti join e accesso a tabelle enormi).
23. Chiudere sempre le query con ordinamenti grandi
Finché una query SQL con ordinamento (ORDER BY, GROUP BY, UNION, distinct) non viene chiusa, Firebird mantiene i record ordinati in memoria. La dimensione della memoria allocata per l’ordinamento è impostata dal parametro TempCacheLimit in firebird.conf, per impostazione predefinita è 64Mb.
Anche con TempCacheLimit aumentato, le query di lunga durata con un gran numero di record ordinati consumeranno prima o poi tutta la quantità allocata e, di conseguenza, l’ordinamento passerà ai file temporanei (cioè al disco). Di conseguenza, ciò può portare a una significativa lentezza.
La raccomandazione è di chiudere tempestivamente tutte queste query.
Domande?
Non esitare a contattarmi per qualsiasi domanda: [email protected]!