Datenbank Benchmarks mit Citus-Benchmark

Wer meiner kleinen Reise in den Hasenbau aus Patroni, pg_auto_failover und Citus bis hierhin gefolgt ist, konnte sich ungefähr denken, was jetzt noch kommen muß: Benchmarking. Und auch dafür gibt es etwas im Citus Repository: Citus-Benchmark.

Die Installation erfolgt einfach nach Readme z. B. in einer Ubuntu Focal VM. Citus-Benchmark verwendet den HammerDB Benchmark und den CHbenCHmark in einem Rutsch. Der HammerDB Benchmark wird i. W. über die Anzahl der Warehouses und die Anzahl der virtuellen User parameterisiert. Für einen schnellen Durchlauf sollte man diese Werte anpassen - sonst vergeht sehr viel Zeit mit dem Anlegen der Warehouses und der User. Das entspricht den Werten

  • pg_count_ware
  • pg_num_vu

Am Ende wirft Citus-Benchmark im Log eine Zeile aus, die bei mir beim ersten Lauf so aussah:

Vuser 1:TEST RESULT : System achieved 3199 NOPM from 7441 PostgreSQL TPM

NOPM entspricht "New Operations per Minute" und TPM "Transactions per Minute". Dabei liegt NOPM meist bei einem Drittel bis zu 45% vom TPM Wert.

Den ersten Wert hatte ich mit einem Citus HA-Setup mit drei Worker-Clustern erreicht, wobei die Worker 2 GB Memory und eine unbehandelte Postgres-Konfiguration hatten.

Die SmartOS Container verwenden ZFS als Filesystem. Die ZFS-Parameter lassen sich in Triton für die einzelne Zone nicht verändern und sehen so aus:

[root@meinserver2 (my-dc-2) ~]# zfs get all /zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca                                                                                                                               
NAME                                        PROPERTY              VALUE                                             SOURCE                                                                                          
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  type                  filesystem                                        -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  creation              Fr. Apr. 28 13:17 2023                            -                                                                                               
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  used                  18,3M                                             -                                                                                               
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  available             200G                                              -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  referenced            950M                                              -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  compressratio         3.74x                                             -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  mounted               yes                                               -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  origin                zones/8b416b22-3421-4c0f-b299-99a72832df6d@final  -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  quota                 200G                                              local
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  reservation           none                                              default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  recordsize            128K                                              default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  mountpoint            /zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca       default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  sharenfs              off                                               default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  checksum              on                                                default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  compression           lz4                                               inherited from zones
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  atime                 off                                               inherited from zones
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  devices               off                                               local
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  exec                  on                                                default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  setuid                on                                                default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  readonly              off                                               default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  zoned                 off                                               default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  snapdir               hidden                                            default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  aclmode               discard                                           default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  aclinherit            restricted                                        default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  createtxg             30632339                                          -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  canmount              on                                                default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  xattr                 on                                                default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  copies                1                                                 default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  version               5                                                 -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  utf8only              off                                               -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  normalization         none                                              -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  casesensitivity       sensitive                                         -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  vscan                 off                                               default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  nbmand                off                                               default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  sharesmb              off                                               default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  refquota              none                                              default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  refreservation        none                                              default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  guid                  7176302598233027976                               -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  primarycache          all                                               default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  secondarycache        all                                               default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  usedbysnapshots       0                                                 -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  usedbydataset         18,3M                                             -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  usedbychildren        0                                                 -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  usedbyrefreservation  0                                                 -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  logbias               latency                                           default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  dedup                 off                                               default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  mlslabel              none                                              default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  sync                  standard                                          default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  dnodesize             legacy                                            default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  refcompressratio      2.20x                                             -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  written               18,3M                                             -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  logicalused           63,4M                                             -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  logicalreferenced     1,97G                                             -
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  filesystem_limit      none                                              default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  snapshot_limit        none                                              default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  filesystem_count      none                                              default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  snapshot_count        none                                              default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  redundant_metadata    all                                               default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  special_small_blocks  0                                                 default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  encryption            off                                               default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  keylocation           none                                              default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  keyformat             none                                              default
zones/0b0f3858-a66b-4773-bdf3-1f77f70063ca  pbkdf2iters           0                                                 default

Die meisten Parameter, die im Zusammenhang mit den Betrieb von Postgres genannt werden, haben schon die richtige Einstellung  (recordsize, compression, etc.). Auf Datenbankseite wurden folgende Werte zur Leistungsverbesserung empfohlen:

  • max_connections habe ich auf von 100 auf 400 gesetzt
  • full_page_writes auf off
  • max_prepared_transactions habe ich auf 400 gesetzt, weil Patroni sonst offenbar dort 400400 einträgt (möglicherweise ein Patroni Bug)
  • 8 GB Memory statt 2 GB - danach dann shared_buffers auf 2GB hochgesetzt
  • wal_sync_method auf fdatasync - wurde für Solaris/SmartOS empfohlen

Die Werte trägt man einfach in die patroni.yml  Datei bzw. das entsprechende Template ein:

scope: ${consul_scope}
namespace: ${consul_namespace}
name: ${hostname}

restapi:
  listen: ${listen_ip}:8008
  connect_address: ${listen_ip}:8008

consul:
  host: localhost:8500
  register_service: true

citus:
  group: 3
  database: citus

bootstrap:
  dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    maximum_lag_on_failover: 1048576
    postgresql:
      use_pg_rewind: true
      parameters:
        max_connections: '400'
        full_page_writes: 'off'
        max_prepared_transactions: '400'
        shared_buffers: '2GB'
        wal_sync_method: 'fdatasync'

Patroni trägt die Werte dann in die postgresql.conf ein und initialisiert die Datenbank dann damit.

Auf diese Weise kam bei drei Worker Clustern dann folgender Wert zustande:

Vuser 1:TEST RESULT : System achieved 26708 NOPM from 61595 PostgreSQL TPM

Ich habe jetzt noch ein viertes Cluster dazugestellt und den Test nochmal angeworfen...

Es war gar nicht so einfach, den Wert nochmal zu erreichen. Ohne Änderung - einfach nur mit einem vierten Worker-Cluster - hat er sich sogar auf ca. 24000 NOPM verschlechtert. Ein Upgrade auf Citus 11.3.0 hat auch keine Veränderung gebracht. Eine Erhöhung der shared_buffers auf 500MB auf den Coordinator Nodes brachte auch keine Verbesserung.

Erst als ich für die Coordinator Nodes 4GB Arbeitsspeicher eingestellt und damit dann 1GB für shared_buffers konfigurieren konnte, ließ sich der Wert (fast) wieder erreichen: Vuser 1:TEST RESULT : System achieved 26423 NOPM from 60946 PostgreSQL TPM.

Es scheint also nicht automatisch so zu sein, daß mit mehr Worker Clustern bei gleichbleibender Workload mehr zu schaffen ist. Mal sehen, wie das mit mehr Warehouses und mehr virtuellen Usern aussieht.

Auch da ergibt sich kein anderes Bild: Mehr User (250) und mehr Warehouses (300) ergeben bei vier Worker Clustern Vuser 1:TEST RESULT : System achieved 20989 NOPM from 48403 PostgreSQL TPM. Möglicherweise muß man da noch mehr Parameter ändern.

Ok - nun habe ich das Setup in die erste OpenStack-Umgebung repliziert. Dort kann ich erstmal nur VMs provisionieren. Ich habe mich für Debian 11 mit acht GB RAM und 8 vCPUs entschieden. Das einzige Tuning, das ich vorgenommen habe ist, shared_buffers auch auf zwei Gigabyte zu setzen. Weitere Tuning-Tipps muß ich erst noch ermitteln. Das Ergebnis war dementsprechend ernüchternd: Vuser 1:TEST RESULT : System achieved 8148 NOPM from 18827 PostgreSQL TPM.  

Bessere Hardware bringt aber offenbar auch bessere Ergebnisse. Dasselbe Setup in einer produktiven OpenStack-Umgebung liefert: TEST RESULT : System achieved 31667 NOPM from 72774 PostgreSQL TPM. Wie gesagt - Postgres noch weitgehend ungetuned.