Rendimiento de confirmación lenta de PostgreSQL

9

Estamos teniendo algunos problemas con una configuración de PostgreSQL. Después de algunos puntos de referencia, descubrí que las consultas muy simples están tomando un tiempo relativamente largo, luego de una inspección adicional parece que el comando COMMIT real es realmente lento.

Ejecuté una prueba muy simple usando la siguiente tabla:

CREATE TABLE test (
    id serial primary key,
    foo varchar(16),
);

Después de activar el inicio de sesión en todas las declaraciones, ejecuté la siguiente consulta 10000 veces:

BEGIN;
INSERT INTO test (a) VALUES ('bar');
COMMIT;

El BEGIN y el INSERT están tardando <1 ms en completarse, pero el COMMIT está tardando un promedio de 22 ms en completarse.

Ejecutar el mismo punto de referencia en mi propia PC, que es mucho más lento, produce el mismo promedio para las declaraciones BEGIN e INSERT, pero el COMMIT promedio es de alrededor de 0.4 ms (más de 20 veces más rápido).

Después de leer un poco, probé la pg_test_fsyncherramienta para tratar de localizar el problema. En el servidor obtengo estos resultados:

$ ./pg_test_fsync -o 1024
1024 operations per test
O_DIRECT supported on this platform for open_datasync and open_sync.

Compare file sync methods using one 8kB write:
(in wal_sync_method preference order, except fdatasync
is Linux's default)
        open_datasync                      14.875 ops/sec
        fdatasync                          11.920 ops/sec
        fsync                              30.524 ops/sec
        fsync_writethrough                            n/a
        open_sync                          30.425 ops/sec

Compare file sync methods using two 8kB writes:
(in wal_sync_method preference order, except fdatasync
is Linux's default)
        open_datasync                      19.956 ops/sec
        fdatasync                          23.299 ops/sec
        fsync                              21.955 ops/sec
        fsync_writethrough                            n/a
        open_sync                           3.619 ops/sec

Compare open_sync with different write sizes:
(This is designed to compare the cost of writing 16kB
in different write open_sync sizes.)
        16kB open_sync write                5.923 ops/sec
         8kB open_sync writes               3.120 ops/sec
         4kB open_sync writes              10.246 ops/sec
         2kB open_sync writes               1.787 ops/sec
         1kB open_sync writes               0.830 ops/sec

Test if fsync on non-write file descriptor is honored:
(If the times are similar, fsync() can sync data written
on a different descriptor.)
        write, fsync, close                34.371 ops/sec
        write, close, fsync                36.527 ops/sec

Non-Sync'ed 8kB writes:
        write                           248302.619 ops/sec

En mi propia PC obtengo:

$ ./pg_test_fsync -o 1024
1024 operations per test
O_DIRECT supported on this platform for open_datasync and open_sync.

Compare file sync methods using one 8kB write:
(in wal_sync_method preference order, except fdatasync
is Linux's default)
        open_datasync                      69.862 ops/sec
        fdatasync                          68.871 ops/sec
        fsync                              34.593 ops/sec
        fsync_writethrough                            n/a
        open_sync                          26.595 ops/sec

Compare file sync methods using two 8kB writes:
(in wal_sync_method preference order, except fdatasync
is Linux's default)
        open_datasync                      26.872 ops/sec
        fdatasync                          59.056 ops/sec
        fsync                              34.031 ops/sec
        fsync_writethrough                            n/a
        open_sync                          17.284 ops/sec

Compare open_sync with different write sizes:
(This is designed to compare the cost of writing 16kB
in different write open_sync sizes.)
        16kB open_sync write                7.412 ops/sec
         8kB open_sync writes               3.942 ops/sec
         4kB open_sync writes               8.700 ops/sec
         2kB open_sync writes               4.161 ops/sec
         1kB open_sync writes               1.492 ops/sec

Test if fsync on non-write file descriptor is honored:
(If the times are similar, fsync() can sync data written
on a different descriptor.)
        write, fsync, close                35.086 ops/sec
        write, close, fsync                34.043 ops/sec

Non-Sync'ed 8kB writes:
        write                           240544.985 ops/sec

La configuración del servidor:

CPU: Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz
RAM: 32GB
Disk: 2x 2TB SATA disk in Software RAID 1

La máquina utilizada para la comparación es un i5 con 16 GB de RAM y discos SATA simples (sin incursiones).

Más información:

  • SO: servidor Ubuntu 12.10
  • Kernel: Linux ... 3.5.0-22-generic # 34-Ubuntu SMP martes 8 de enero 21:47:00 UTC 2013 x86_64 x86_64 x86_64 GNU / Linux
  • RAID de software 1
  • El sistema de archivos es ext4
  • No hay otras opciones de montaje especificadas.
  • Postgres versión 9.1
  • Incursión mdadm en Linux

Salida de dump2efs:

dumpe2fs 1.42.5 (29-Jul-2012)
Filesystem volume name:   <none>
Last mounted on:          /
Filesystem UUID:          16e30b20-0531-4bcc-877a-818e1f5d5fb2
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
Filesystem flags:         signed_directory_hash 
Default mount options:    (none)
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              182329344
Block count:              729289039
Reserved block count:     36464451
Free blocks:              609235080
Free inodes:              182228152
First block:              0
Block size:               4096
Fragment size:            4096
Reserved GDT blocks:      850
Blocks per group:         32768
Fragments per group:      32768
Inodes per group:         8192
Inode blocks per group:   256
RAID stride:              1
Flex block group size:    16
Filesystem created:       Sat Jan 19 12:42:19 2013
Last mount time:          Wed Jan 23 16:23:11 2013
Last write time:          Sat Jan 19 12:46:13 2013
Mount count:              8
Maximum mount count:      30
Last checked:             Sat Jan 19 12:42:19 2013
Check interval:           15552000 (6 months)
Next check after:         Thu Jul 18 13:42:19 2013
Lifetime writes:          257 GB
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:           128
Journal inode:            8
First orphan inode:       17304375
Default directory hash:   half_md4
Directory Hash Seed:      a71fa518-7696-4a28-bd89-b21c10d4265b
Journal backup:           inode blocks
Journal features:         journal_incompat_revoke
Journal size:             128M
Journal length:           32768
Journal sequence:         0x000df5a4
Journal start:            31733

Mdadm - salida de detalles:

/dev/md2:
        Version : 1.2
  Creation Time : Sat Jan 19 12:42:05 2013
     Raid Level : raid1
     Array Size : 2917156159 (2782.02 GiB 2987.17 GB)
  Used Dev Size : 2917156159 (2782.02 GiB 2987.17 GB)
   Raid Devices : 2
  Total Devices : 2
    Persistence : Superblock is persistent

    Update Time : Fri Mar 22 11:16:45 2013
          State : clean 
 Active Devices : 2
Working Devices : 2
 Failed Devices : 0
  Spare Devices : 0

           Name : rescue:2
           UUID : d87b98e7:d584a4ed:5dac7907:ae5639b0
         Events : 38

    Number   Major   Minor   RaidDevice State
       0       8        3        0      active sync   /dev/sda3
       1       8       19        1      active sync   /dev/sdb3

Actualización 2013-03-25 : Ejecuté una prueba inteligente larga en ambos discos, que no reveló ningún problema. Ambos discos son de Seagate, modelo: ST3000DM001-9YN166.

Actualización 2013-03-27 : Ejecuté pg_test_fsync de la última versión (9.2.3) en una máquina completamente inactiva:

$ ./pg_test_fsync -s 3
3 seconds per test
O_DIRECT supported on this platform for open_datasync and open_sync.

Compare file sync methods using one 8kB write:
(in wal_sync_method preference order, except fdatasync
is Linux's default)
        open_datasync                      39.650 ops/sec
        fdatasync                          34.283 ops/sec
        fsync                              19.309 ops/sec
        fsync_writethrough                            n/a
        open_sync                          55.271 ops/sec

Es un poco mejor que antes, pero aún deplorable. Las particiones en ambos discos están alineadas:

$ sudo parted /dev/sdb unit s print
Model: ATA ST3000DM001-9YN1 (scsi)
Disk /dev/sdb: 5860533168s
Sector size (logical/physical): 512B/4096B
Partition Table: gpt

Number  Start      End          Size         File system  Name  Flags
 4      2048s      4095s        2048s                           bios_grub
 1      4096s      25169919s    25165824s                       raid
 2      25169920s  26218495s    1048576s                        raid
 3      26218496s  5860533134s  5834314639s                     raid

Montar -v salida:

$ mount -v | grep ^/dev/
/dev/md2 on / type ext4 (rw,noatime)
/dev/md1 on /boot type ext3 (rw)

El dispositivo md2 se está utilizando para las pruebas. Vamos a destruir la partición de intercambio y ejecutar pg_test_fsync en discos individuales.

Si ejecuto pg_test_fsync en ambos discos individualmente, obtengo aproximadamente el mismo rendimiento, la partición se montó con noatime:

$ pg_test_fsync/pg_test_fsync -s 3

3 seconds per test
O_DIRECT supported on this platform for open_datasync and open_sync.

Compare file sync methods using one 8kB write:
(in wal_sync_method preference order, except fdatasync
is Linux's default)
        open_datasync                      75.111 ops/sec
        fdatasync                          71.925 ops/sec
        fsync                              37.352 ops/sec
        fsync_writethrough                            n/a
        open_sync                          33.746 ops/sec

Compare file sync methods using two 8kB writes:
(in wal_sync_method preference order, except fdatasync
is Linux's default)
        open_datasync                      38.204 ops/sec
        fdatasync                          49.907 ops/sec
        fsync                              32.126 ops/sec
        fsync_writethrough                            n/a
        open_sync                          13.642 ops/sec

Compare open_sync with different write sizes:
(This is designed to compare the cost of writing 16kB
in different write open_sync sizes.)
         1 * 16kB open_sync write          25.325 ops/sec
         2 *  8kB open_sync writes         12.539 ops/sec
         4 *  4kB open_sync writes          6.207 ops/sec
         8 *  2kB open_sync writes          3.098 ops/sec
        16 *  1kB open_sync writes          1.208 ops/sec

Test if fsync on non-write file descriptor is honored:
(If the times are similar, fsync() can sync data written
on a different descriptor.)
        write, fsync, close                27.275 ops/sec
        write, close, fsync                20.561 ops/sec

Non-Sync'ed 8kB writes:
        write                           562902.020 ops/sec

Después de ejecutar la prueba un par de veces, tanto en la matriz como en el disco único, los números parecen variar enormemente. En el peor de los casos, el rendimiento es aproximadamente el 50% de lo que publiqué aquí (alrededor de 30 operaciones / s para la primera prueba). ¿Es esto normal? La máquina está completamente inactiva, todo el tiempo.

Además, según la salida dmesg, el controlador está en modo AHCI.

Grasa de ballena
fuente
¿Puede proporcionar algunos detalles sobre ese software RAID? Que software ¿Linux mdadmo dmraid? ¿Algo específico del vendedor? ¿Algo más? Su versión de PostgreSQL y la versión del sistema operativo host también ayudarían.
Craig Ringer

Respuestas:

6

El servidor tiene un fsyncrendimiento increíblemente indescriptible y sorprendentemente lento . Hay algo muy mal con la configuración de RAID 1 de su software. El terrible fsyncrendimiento es casi seguro la causa de sus problemas de rendimiento.

El escritorio simplemente tiene muy lento fsync.

Puede solucionar los problemas de rendimiento a costa de perder algunos datos después de un bloqueo configurando synchronous_commit = offy configurando a commit_delay. Sin embargo, realmente necesita clasificar el rendimiento del disco en el servidor, eso es asombrosamente lento.

A modo de comparación, esto es lo que obtengo en mi computadora portátil (i7, 8GB RAM, SSD 128G de rango medio, pg_test_fsync de 9.2):

Compare file sync methods using one 8kB write:

        open_datasync                    4445.744 ops/sec
        fdatasync                        4225.793 ops/sec
        fsync                            2742.679 ops/sec
        fsync_writethrough                            n/a
        open_sync                        2907.265 ops/sec

Es cierto que este SSD probablemente no sea seguro para la pérdida de energía, pero no es como un SSD decente a prueba de fallas que cuesta mucho cuando hablamos de los costos del servidor.

Craig Ringer
fuente
1
Sí, pero ¿qué está causando el mal rendimiento de fsync?
Blubber
Intenté ejecutar pg_test_fsync en mi propio SSD y obtuve cifras de rendimiento comparables. Sé que podría deshabilitar las confirmaciones de sincronización, pero la pregunta sigue siendo, ¿cuál es la causa de este problema?
Blubber
@Blubber ¿Qué software RAID está utilizando? ¿Qué sistema de archivos? ¿Qué sistema operativo y versión de host? ¿Qué opciones de montaje del sistema de archivos? Toda esta información es crítica si está buscando la causa raíz; por favor actualice su pregunta. También debe hacer comprobaciones de estado INTELIGENTES en los discos duros ( smartctl -d ata -a /dev/sdx|lessy smartctl -d ata -t long /dev/sdxseguidos por uno sleep 90mo lo que smartctlle indique seguido por otro -d ata -apara obtener los resultados).
Craig Ringer
@Blubber Incluso si soluciona los problemas de RAID, su rendimiento seguirá siendo malo, pero no tan malo. Los discos viejos de 7200 RPM (o, peor aún, 5400 RPM) son una mala opción para el rendimiento de la base de datos, especialmente sin un controlador RAID de hardware adecuado con caché respaldada por batería que permita que el controlador se agrupe y escriba en el búfer.
Craig Ringer
He actualizado la pregunta con más detalles sobre el sistema de archivos y la configuración de la incursión. Entiendo que esta máquina nunca dará un rendimiento muy bueno en su configuración actual. Pero el rendimiento actual es realmente malo.
Blubber
1

Esto se pg_test_fsyncemite en mi servidor, con una configuración muy similar: software Linux RAID1 en 2 discos de nivel de consumidor ( WD10EZEX-00RKKA0):

# ./pg_test_fsync -s 3
Compare file sync methods using one 8kB write:
(in wal_sync_method preference order, except fdatasync
is Linux's default)
        open_datasync                     115.375 ops/sec
        fdatasync                         109.369 ops/sec
        fsync                              27.081 ops/sec
        fsync_writethrough                            n/a
        open_sync                         112.042 ops/sec
...

Usted probó esto en un servidor completamente inactivo, ¿verdad?


Tal vez tienes particiones no alineadas. Cheque:

parted /dev/sda unit s print

Esta es la salida de mi servidor:

Model: ATA WDC WD10EZEX-00R (scsi)
Disk /dev/sda: 1953525168s
Sector size (logical/physical): 512B/4096B
Partition Table: msdos

Number  Start       End          Size         Type     File system     Flags
 1      2048s       67110911s    67108864s    primary  ext4            boot, raid
 2      67110912s   603981823s   536870912s   primary                  raid
 3      603981824s  608176127s   4194304s     primary  linux-swap(v1)
 4      608176128s  1953523711s  1345347584s  primary                  raid

Verifique que cada número en la Startcolumna sea divisible por 2048 (lo que significa 1MiB). Para una buena alineación 4096B divisible por 4 sería suficiente, pero las utilidades conscientes de la alineación comienzan las particiones en los límites de 1MiB.


Además, tal vez esté utilizando opciones de montaje no predeterminadas, como data=journalque tienen un gran impacto en el rendimiento. Mostrar su: mount -v | grep ^/dev/. Esto es mío:

/dev/md0 on / type ext4 (rw,barrier,usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0)
/dev/md2 on /home type ext4 (rw,barrier,usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0)
/dev/md1 on /var type ext4 (rw,barrier,usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0)

Quizás uno de tus discos está roto. Cree una partición en cada disco sin RAID (tal vez haya reservado algunas particiones de intercambio en ambos discos; úselas; de todos modos, no hay uso de RAID en el intercambio). Cree sistemas de archivos allí y ejecútelos pg_test_fsyncen cada unidad; si uno tiene problemas, uno bueno tendría que esperar cuando ambos se reflejen.


Verifique que su BIOS esté configurado para usar el modo AHCI en lugar del modo IDE. Un servidor se beneficiaría de Native Command Queuing , que no está disponible en modo IDE.


Ignorar la comparación con SSD. Es ridículo comparar.

Tometzky
fuente
Ejecuté bonnie ++, que muestra un buen rendimiento (tan bueno como cabría esperar de los discos sata normales). Además, las particiones están alineadas. Cuando ejecuté pg_test_fsync la primera vez que estaba en una VM. Luego lo ejecuté en el hardware real, después de apagar todos los demás procesos (incluidas las máquinas virtuales). El rendimiento fue un poco mejor, alrededor de 40 operaciones / segundo, que aún es deplorable. Voy a hacer algunas pruebas más, en particiones separadas si tengo tiempo hoy. Gracias por todas las sugerencias.
Blubber
He modificado mi pregunta original con información adicional sobre las opciones de montaje y la alineación de la partición.
Blubber
1

Sé que podría ser demasiado tarde para responder esto. He estado viendo problemas de rendimiento similares con PostgreSQL y MySQL, cuando uso O_DIRECT. Micro-comparé el sistema usando iozone con escrituras de sincronización (opción - + r) y con y sin O_DIRECT (opción -I). A continuación se muestran los dos comandos que utilicé:

iozone -s 2g -r 512k -+r -I -f /mnt/local/iozone_test_file -i 0

y

iozone -s 2g -r 512k -+r    -f /mnt/local/iozone_test_file -i 0

El primero es O_SYNC + O_DIRECT, mientras que el segundo es solo O_SYNC. Con el primero estaba obteniendo aproximadamente 30 MB / seg y con el segundo obtenía unos 220 MB / seg (unidad SSD). Lo que descubrí fue que la opción has_journal en costuras ext4 causa el problema. No sé realmente por qué ...

Filesystem features:      has_journal 

Una vez que saqué esta opción, las cosas comenzaron a funcionar bien, ambas pruebas alcanzaron y mantuvieron 220 MB / seg. Para eliminar la opción, puede usar algo como:

tune2fs -O ^has_journal /dev/sdX

Puede probarlo y ver si resuelve sus problemas de rendimiento.

scribul
fuente
1
Deshabilitar el diario en ext3 / 4 no es algo que se haga sin una cuidadosa consideración y una muy buena comprensión del impacto.
ThatGraemeGuy
2
Estoy en desacuerdo. Un DBMS realiza su propio registro y recuperación para proporcionar durabilidad y atomicidad de las transacciones. El diario FS es completamente inútil en ese sentido. Mientras fsync funcione correctamente, los efectos de las transacciones confirmadas siempre se pueden restaurar.
Caetano Sauer