Come ottimizzare il database per I / O pesanti dagli aggiornamenti (software e hardware)


20

La situazione in mio possesso è un database Postgresql 9.2 che è costantemente aggiornato costantemente. Il sistema è quindi associato all'I / O e al momento sto pensando di fare un altro aggiornamento, ho solo bisogno di alcune indicazioni su dove iniziare a migliorare.

Ecco una foto di come appariva la situazione negli ultimi 3 mesi:

inserisci qui la descrizione dell'immagine

Come puoi vedere, aggiorna gli account delle operazioni per la maggior parte dell'utilizzo del disco. Ecco un'altra immagine di come appare la situazione in una finestra di 3 ore più dettagliata:

inserisci qui la descrizione dell'immagine

Come puoi vedere, la velocità di scrittura massima è di circa 20 MB / s

Software Il server esegue Ubuntu 12.04 e Postgresql 9.2. Il tipo di aggiornamenti sono piccoli aggiornamenti in genere su singole righe identificate da ID. Es UPDATE cars SET price=some_price, updated_at = some_time_stamp WHERE id = some_id. Ho rimosso e ottimizzato gli indici per quanto penso sia possibile, e anche la configurazione dei server (sia kernel Linux che postgres conf) è piuttosto ottimizzata.

Hardware L'hardware è un server dedicato con RAM ECC da 32 GB, 4 dischi SAS da 600 GB 15.000 rpm in un array RAID 10, controllato da un controller raid LSI con BBU e un processore Intel Xeon E3-1245 Quadcore.

Domande

  • Le prestazioni viste dai grafici sono ragionevoli per un sistema di questo calibro (lettura / scrittura)?
  • Dovrei quindi concentrarmi sul fare un aggiornamento dell'hardware o approfondire il software (ottimizzazione del kernel, conf, query ecc.)?
  • Se si esegue un aggiornamento hardware, il numero di dischi è fondamentale per le prestazioni?

------------------------------AGGIORNARE------------------- ----------------

Ora ho aggiornato il mio server di database con quattro SSD Intel 520 anziché i vecchi dischi SAS da 15k. Sto usando lo stesso controller raid. Le cose sono migliorate parecchio, come puoi vedere dalle seguenti prestazioni di I / O di picco sono migliorate circa 6-10 volte - ed è fantastico !. inserisci qui la descrizione dell'immagine Tuttavia, mi aspettavo qualcosa di più simile a un miglioramento di 20-50 volte in base alle risposte e alle capacità di I / O dei nuovi SSD. Quindi ecco un'altra domanda.

Nuova domanda C'è qualcosa nella mia configurazione attuale, che sta limitando le prestazioni I / O del mio sistema (dov'è il collo di bottiglia)?

Le mie configurazioni:

/etc/postgresql/9.2/main/postgresql.conf

data_directory = '/var/lib/postgresql/9.2/main'
hba_file = '/etc/postgresql/9.2/main/pg_hba.conf'
ident_file = '/etc/postgresql/9.2/main/pg_ident.conf'
external_pid_file = '/var/run/postgresql/9.2-main.pid'
listen_addresses = '192.168.0.4, localhost'
port = 5432
unix_socket_directory = '/var/run/postgresql'
wal_level = hot_standby
synchronous_commit = on
checkpoint_timeout = 10min
archive_mode = on
archive_command = 'rsync -a %p postgres@192.168.0.2:/var/lib/postgresql/9.2/wals/%f </dev/null'
max_wal_senders = 1
wal_keep_segments = 32
hot_standby = on
log_line_prefix = '%t '
datestyle = 'iso, mdy'
lc_messages = 'en_US.UTF-8'
lc_monetary = 'en_US.UTF-8'
lc_numeric = 'en_US.UTF-8'
lc_time = 'en_US.UTF-8'
default_text_search_config = 'pg_catalog.english'
default_statistics_target = 100
maintenance_work_mem = 1920MB
checkpoint_completion_target = 0.7
effective_cache_size = 22GB
work_mem = 160MB
wal_buffers = 16MB
checkpoint_segments = 32
shared_buffers = 7680MB
max_connections = 400 

/etc/sysctl.conf

# sysctl config
#net.ipv4.ip_forward=1
net.ipv4.conf.all.rp_filter=1
net.ipv4.icmp_echo_ignore_broadcasts=1
# ipv6 settings (no autoconfiguration)
net.ipv6.conf.default.autoconf=0
net.ipv6.conf.default.accept_dad=0
net.ipv6.conf.default.accept_ra=0
net.ipv6.conf.default.accept_ra_defrtr=0
net.ipv6.conf.default.accept_ra_rtr_pref=0
net.ipv6.conf.default.accept_ra_pinfo=0
net.ipv6.conf.default.accept_source_route=0
net.ipv6.conf.default.accept_redirects=0
net.ipv6.conf.default.forwarding=0
net.ipv6.conf.all.autoconf=0
net.ipv6.conf.all.accept_dad=0
net.ipv6.conf.all.accept_ra=0
net.ipv6.conf.all.accept_ra_defrtr=0
net.ipv6.conf.all.accept_ra_rtr_pref=0
net.ipv6.conf.all.accept_ra_pinfo=0
net.ipv6.conf.all.accept_source_route=0
net.ipv6.conf.all.accept_redirects=0
net.ipv6.conf.all.forwarding=0
# Updated according to postgresql tuning
vm.dirty_ratio = 10
vm.dirty_background_ratio = 1
vm.swappiness = 0
vm.overcommit_memory = 2
kernel.sched_autogroup_enabled = 0
kernel.sched_migration_cost = 50000000

/etc/sysctl.d/30-postgresql-shm.conf

# Shared memory settings for PostgreSQL
# Note that if another program uses shared memory as well, you will have to
# coordinate the size settings between the two.
# Maximum size of shared memory segment in bytes
#kernel.shmmax = 33554432
# Maximum total size of shared memory in pages (normally 4096 bytes)
#kernel.shmall = 2097152
kernel.shmmax = 8589934592
kernel.shmall = 17179869184
# Updated according to postgresql tuning

Uscita di MegaCli64 -LDInfo -LAll -aAll

Adapter 0 -- Virtual Drive Information:
Virtual Drive: 0 (Target Id: 0)
Name                :
RAID Level          : Primary-1, Secondary-0, RAID Level Qualifier-0
Size                : 446.125 GB
Sector Size         : 512
Is VD emulated      : No
Mirror Data         : 446.125 GB
State               : Optimal
Strip Size          : 64 KB
Number Of Drives per span:2
Span Depth          : 2
Default Cache Policy: WriteBack, ReadAhead, Direct, Write Cache OK if Bad BBU
Current Cache Policy: WriteBack, ReadAhead, Direct, Write Cache OK if Bad BBU
Default Access Policy: Read/Write
Current Access Policy: Read/Write
Disk Cache Policy   : Disk's Default
Encryption Type     : None
Is VD Cached: No

(1) .Se le colonne non sono indicizzate, puoi sfruttare HOT (vedi git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/… ). (2). Prova con synchronous_commit = off, dopo aver letto i documenti su postgresql.org/docs/9.2/static/wal-async-commit.html . (3). Come appare la tua configurazione? Per esempio. risultati di questa query:SELECT name, current_setting(name), source FROM pg_settings WHERE source NOT IN ('default', 'override');
bma

@bma Consentitemi di aggiungere l'avvertimento su synchronous_commit: "Il commit asincrono è un'opzione che consente il completamento più rapido delle transazioni, al costo che le transazioni più recenti potrebbero andare perse in caso di arresto anomalo del database".
dezso,

@dezso Avrei dovuto essere più esplicito sulla sezione dei documenti a cui mi riferivo. Grazie per il chiarimento. Il motivo per cui l'ho sollevato è perché uno dei nostri server sotto carico (utilizzando Hibernate) stava soffrendo, quindi ho preso una decisione informata per passare al commit asincrono e il 40% del carico è praticamente scomparso. Non raccomandato per la maggior parte dei sistemi, ma in alcuni casi può farti guadagnare tempo tra gli aggiornamenti del server e le modifiche delle applicazioni.
bma,

Risposte:


10

Se si esegue un aggiornamento hardware, il numero di dischi è fondamentale per le prestazioni?

Sì, poiché un disco rigido - anche SAS - ha una testa che richiede tempo per muoversi.

Vuoi un aggiornamento ENORME?

Uccidi i dischi SAS, vai su SATA. Collega l'SSD SATA a livello aziendale, come il Samsung 843T.

Risultato? È possibile eseguire circa 60.000 IOPS (ovvero 60 mila) per unità.

Questo è il motivo per cui gli SSD sono killer nello spazio DB e molto più economici di qualsiasi unità SAS. Il disco filato phyiscal non riesce a tenere il passo con le capacità IOPS dei dischi.

I tuoi dischi SAS sono stati una scelta mediocre per iniziare (troppo grande per ottenere molti IOPS) Per un database di uso più elevato (dischi più piccoli significherebbero molti più IOPS), ma alla fine SSD è il punto di svolta qui.

Per quanto riguarda software / kernel. Qualsiasi database decente farà molti IOPS e scaricherà i buffer. Il file di registro deve essere SCRITTO per garantire le condizioni ACID di base. Le uniche melodie del kernel che potresti fare invaliderebbero la tua integrità transazionale - parzialmente PUOI cavartela. Il controller Raid in modalità write back lo farà - confermerà la scrittura come svuotata anche se non lo è - ma può farlo perché si presume che la BBU salvi il giorno in cui si verifica un'interruzione di corrente. Qualunque cosa tu faccia più in alto nel kernel - meglio sapere che puoi vivere con gli effetti collaterali negativi.

Alla fine, i database hanno bisogno di IOPS e potresti essere sorpreso di vedere quanto è piccola la tua configurazione rispetto ad altri qui. Ho visto banche dati con oltre 100 dischi solo per ottenere gli IOPS di cui avevano bisogno. Ma davvero, oggi, acquisti SSD e vai su per loro - sono così superiori nelle funzionalità IOPS, non ha senso combattere questo gioco con le unità SAS.

E sì, i tuoi numeri IOPS non sembrano male per l'hardware. All'interno di quello che mi aspetterei.


6

Se te lo puoi permettere, metti pg_xlog su una coppia di unità RAID 1 separata sul suo controller con RAM supportata da batteria configurata per la riscrittura. Questo è vero anche se è necessario utilizzare spinning rust per pg_xlog mentre tutto il resto è su SSD.

Se si utilizza SSD, assicurarsi che disponga di un supercondensatore o di altri mezzi per conservare tutti i dati memorizzati nella cache in caso di interruzione dell'alimentazione.

In generale, più mandrini significa più larghezza di banda I / O.


Sfortunatamente ho solo quattro slot hdd nel controller raid. Perché dovresti mettere pg_xlogs su un array separato, se tutti gli altri dischi fossero SSD?
Niels Kristian,

2
@NielsKristian Penso di aver ragione quando dico che nella maggior parte dei sistemi il registro delle transazioni è la cosa più pesantemente scritta sul disco. Inoltre, la scrittura avviene sostanzialmente in parallelo con la scrittura dei dati. I due non possono essere eseguiti contemporaneamente con un HDD poiché la testa è su pg_xlog o sulle cartelle dei dati. (Avviso di semplificazione serio!) La separazione dei due compiti divide il carico di I / O su due dischi / array indipendenti.
dezso,

2
Oltre a quanto affermato da @dezso, i dischi rigidi sono OK per l'archiviazione dedicata a WAL perché l'accesso è quasi interamente sequenziale, quindi il tempo di ricerca è minimo ..
kgrittn,

1

Supponendo che tu sia in esecuzione su Linux, assicurati di impostare lo scheduler IO del disco.

Dall'esperienza passata, passare a Noop ti darà una velocità abbastanza sostanziale (specialmente per SSD).

La modifica dello scheduler IO può essere eseguita al volo senza tempi di inattività.

vale a dire. echo noop> / sys / block // queue / scheduler

Vedi: http://www.cyberciti.biz/faq/linux-change-io-scheduler-for-harddisk/ per maggiori informazioni.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.