Benchmarking de Base de Datos con pgbench y mysqlslap

La validación de rendimiento de base de datos requiere herramientas específicamente diseñadas para generar cargas de trabajo transaccionales realistas y medir respuesta del sistema. pgbench para PostgreSQL y mysqlslap para MySQL proporcionan métodos estándar de la industria para benchmarking de bases de datos, permitiendo planificación de capacidad y optimización de rendimiento. Esta guía cubre despliegue de ambas herramientas para análisis exhaustivo de rendimiento de base de datos.

Tabla de Contenidos

  1. pgbench para PostgreSQL
  2. Configuración de Carga de Trabajo de pgbench
  3. mysqlslap para MySQL
  4. Benchmarking SQL Personalizado
  5. Interpretación de Resultados
  6. Validación de Optimización de Rendimiento
  7. Benchmarking Comparativo
  8. Conclusión

pgbench para PostgreSQL

Instalación y Configuración de pgbench

# pgbench viene con PostgreSQL
psql --version

# Inicializar base de datos pgbench
createdb pgbench

# Generar datos de prueba (factor de escala 10 = 100,000 filas)
pgbench -i -s 10 pgbench

# Parámetros:
# -i: Inicializar (preparar tablas de prueba)
# -s: Factor de escala (determina volumen de datos)

# Verificar tablas generadas
psql pgbench -c "SELECT schemaname, tablename FROM pg_tables WHERE schemaname='public';"

# Ver tamaños de tabla
psql pgbench -c "SELECT tablename, pg_size_pretty(pg_relation_size(schemaname||'.'||tablename)) FROM pg_tables WHERE schemaname='public';"

Prueba Básica de pgbench

# Ejecutar benchmark OLTP básico (10 segundos)
pgbench -r pgbench

# La salida estándar muestra:
# TPS (Transacciones Por Segundo)
# Latencia promedio
# Latencia del percentil 90

# Parámetros de prueba extendida
pgbench -c 10 -j 4 -T 60 pgbench

# Parámetros explicados:
# -c 10: 10 clientes concurrentes
# -j 4: 4 hilos (uno por conexión)
# -T 60: Duración de la prueba de 60 segundos

# Ver tasas de transacciones
pgbench -r -R 1000 pgbench  # Limitado en velocidad a 1000 TPS

Pruebas de Escalabilidad de pgbench

# Probar varios recuentos de clientes
for clients in 1 5 10 20 50; do
  echo "=== $clients clients ==="
  pgbench -c $clients -j $((clients/2)) -T 30 pgbench
done

# Prueba con conjunto de datos más grande
pgbench -i -s 100 pgbench  # 1,000,000 filas

pgbench -c 20 -j 4 -T 60 pgbench

# Monitorear durante la prueba
# En terminal paralela:
watch -n 1 'psql pgbench -c "SELECT count_est FROM pgbench_stats;"'

Configuración de Carga de Trabajo de pgbench

Carga de Trabajo Personalizada de pgbench

# Crear script SQL personalizado
cat > ~/pgbench_custom.sql <<'EOF'
\set aid random(1, 100000 * :scale)
\set bid random(1, 1 * :scale)
\set tid random(1, 10 * :scale)
\set delta random(-5000, 5000)

BEGIN;
UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
COMMIT;
EOF

# Ejecutar carga de trabajo personalizada
pgbench -f ~/pgbench_custom.sql -c 10 -j 4 -T 60 pgbench

Carga de Trabajo Pesada en Lectura

# Crear script de prueba de solo lectura
cat > ~/pgbench_readonly.sql <<'EOF'
\set aid random(1, 100000 * :scale)
BEGIN;
SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
SELECT * FROM pgbench_branches WHERE bid = :aid % 100;
COMMIT;
EOF

# Ejecutar carga de trabajo de lectura
pgbench -f ~/pgbench_readonly.sql -c 20 -j 4 -T 60 -r pgbench

mysqlslap para MySQL

Instalación y Configuración de mysqlslap

# mysqlslap viene con herramientas de cliente MySQL
mysql --version

# Prueba de generación automática básica
mysqlslap --auto-generate-sql --concurrency=10 --number-of-queries=1000

# Conectar a servidor MySQL específico
mysqlslap -h localhost -u root -p --auto-generate-sql --concurrency=10

# Parámetros:
# --auto-generate-sql: Generar SQL aleatorio
# --concurrency: Número de clientes
# --number-of-queries: Total de consultas a ejecutar

Generación de Carga de Trabajo de mysqlslap

# Generar carga de trabajo exhaustiva
mysqlslap \
  --auto-generate-sql \
  --auto-generate-sql-load-type=mixed \
  --concurrency=5,10,15 \
  --number-of-queries=5000 \
  --engine=InnoDB \
  -u root -p

# Tipos de carga de trabajo:
# read: Solo consultas SELECT
# write: INSERT/UPDATE/DELETE
# key: UPDATE con cláusula WHERE
# mixed: Combinación de todos los tipos

# Preservar datos de prueba entre ejecuciones
mysqlslap \
  --create-schema=testdb \
  --auto-generate-sql \
  --preserve-schema-on-disconnect \
  --concurrency=10 \
  --number-of-queries=10000 \
  -u root -p

Consultas Personalizadas de mysqlslap

# Crear script SQL personalizado
cat > ~/mysql_test.sql <<'EOF'
SELECT * FROM test_table WHERE id = @id;
INSERT INTO test_table (name, value) VALUES ('test', RAND());
UPDATE test_table SET value = RAND() WHERE id = @id;
DELETE FROM test_table WHERE id < 100;
EOF

# Ejecutar prueba personalizada
mysqlslap \
  --concurrency=10 \
  --iterations=10 \
  --query=~/mysql_test.sql \
  --create-schema=testdb \
  -u root -p

# Múltiples archivos de consulta
mysqlslap \
  --concurrency=10 \
  --query=~/read_queries.sql \
  --query=~/write_queries.sql \
  -u root -p

Benchmarking SQL Personalizado

Pruebas de Optimización Específicas de Base de Datos

# PostgreSQL: Probar cambios de plan de consulta
cat > test_query_performance.sql <<'EOF'
EXPLAIN ANALYZE
SELECT * FROM large_table WHERE indexed_column = 'value';

-- Después de crear índice
CREATE INDEX idx_indexed_column ON large_table(indexed_column);

EXPLAIN ANALYZE
SELECT * FROM large_table WHERE indexed_column = 'value';
EOF

# Ejecutar antes y después de creación de índice
pgbench -f test_query_performance.sql pgbench

# MySQL: Probar con diferentes motores
cat > test_engine_performance.sql <<'EOF'
ALTER TABLE test_table ENGINE=InnoDB;
-- Ejecutar benchmark
-- Entonces:
ALTER TABLE test_table ENGINE=MyISAM;
-- Ejecutar de nuevo para comparación
EOF

Interpretación de Resultados

Entender Métricas de TPS

# Ejemplo de salida de pgbench:
# transaction type: TPC-B (sort of)
# scaling factor: 10
# number of clients: 10
# number of threads: 4
# number of transactions skipped: 0
# number of transactions processed: 6000
# number of failed transactions: 0
# latency average = 1.667 ms
# latency stddev = 2.551 ms
# latency min = 0.495 ms
# latency max = 45.829 ms
# latency p50 = 1.285 ms
# latency p95 = 3.456 ms
# latency p99 = 7.890 ms
# tps = 599.88 (including connections establishing)
# tps = 600.05 (excluding connections establishing)

# Interpretación:
# Mayor TPS = mejor rendimiento
# Menor latencia = mejor capacidad de respuesta
# Latencia consistente = rendimiento estable

Análisis de Latencia

# Crear script para analizar progresión de latencia
cat > analyze_latency_trend.sh <<'EOF'
#!/bin/bash
echo "time,avg_latency,p95_latency,p99_latency" > latency_trend.csv

for iteration in {1..10}; do
  sleep 60  # Dejar que el sistema se estabilice
  result=$(pgbench -c 20 -j 4 -T 60 pgbench 2>&1)
  
  avg=$(echo "$result" | grep "average" | awk '{print $NF}')
  p95=$(echo "$result" | grep "p95" | awk '{print $NF}')
  p99=$(echo "$result" | grep "p99" | awk '{print $NF}')
  
  echo "$(date +%H:%M:%S),$avg,$p95,$p99" >> latency_trend.csv
done

# Ver resultados
column -t -s, latency_trend.csv
EOF

chmod +x analyze_latency_trend.sh
./analyze_latency_trend.sh

Validación de Optimización de Rendimiento

Comparación Antes/Después de Optimización

# Prueba de línea base
pgbench -c 20 -j 4 -T 60 -r pgbench | tee baseline.txt

# Aplicar optimización (ajustar postgresql.conf)
# shared_buffers = 256MB
# effective_cache_size = 4GB
# work_mem = 20MB

# Recargar configuración
sudo systemctl restart postgresql

# Prueba post-optimización
pgbench -c 20 -j 4 -T 60 -r pgbench | tee after_tuning.txt

# Comparar resultados
echo "=== TPS Comparison ==="
grep "tps =" baseline.txt
grep "tps =" after_tuning.txt

echo "=== Latency Comparison ==="
grep "latency average" baseline.txt
grep "latency average" after_tuning.txt

Pruebas de Impacto de Configuración

# Prueba diferentes configuraciones de caché
for shared_buffers in "64MB" "256MB" "1GB"; do
  # Actualizar postgresql.conf
  sudo sed -i "s/^shared_buffers = .*/shared_buffers = $shared_buffers/" /etc/postgresql/*/main/postgresql.conf
  
  # Reiniciar PostgreSQL
  sudo systemctl restart postgresql
  
  # Ejecutar prueba
  echo "=== Testing shared_buffers=$shared_buffers ==="
  pgbench -c 10 -j 4 -T 60 pgbench | grep "tps ="
done

Benchmarking Comparativo

Comparación de Base de Datos

# Comparar rendimiento de PostgreSQL vs MySQL
echo "=== PostgreSQL Benchmark ==="
pgbench -i -s 50 pgbench
pgbench -c 20 -j 4 -T 60 -r pgbench

echo "=== MySQL Benchmark ==="
mysql -u root -p -e "CREATE DATABASE mysqlslap_test;"

mysqlslap \
  --auto-generate-sql \
  --concurrency=20 \
  --number-of-queries=100000 \
  --engine=InnoDB \
  -u root -p

Comparación de Versiones

# Probar diferentes versiones de PostgreSQL
# Instalar múltiples versiones:
# PostgreSQL 12, 13, 14, 15

# Para cada versión:
# Inicializar clúster, ejecutar benchmark

echo "=== PostgreSQL 14 ==="
/usr/lib/postgresql/14/bin/pgbench -i -s 50 pgbench_14
/usr/lib/postgresql/14/bin/pgbench -c 20 -j 4 -T 60 pgbench_14 | grep "tps ="

echo "=== PostgreSQL 15 ==="
/usr/lib/postgresql/15/bin/pgbench -i -s 50 pgbench_15
/usr/lib/postgresql/15/bin/pgbench -c 20 -j 4 -T 60 pgbench_15 | grep "tps ="

Conclusión

pgbench y mysqlslap proporcionan capacidades esenciales para validación de rendimiento de base de datos y optimización. Al establecer métricas de línea base antes de la optimización, las organizaciones cuantifican mejora a partir de cambios de configuración y actualizaciones de hardware. Entender percentiles de latencia y rendimiento de transacciones permite decisiones informadas sobre planificación de capacidad. El benchmarking regular detecta degradación de rendimiento por envejecimiento de hardware, fragmentación o configuraciones subóptimas. Ya sea validando nueva infraestructura de base de datos, evaluando actualizaciones de versión mayor o demostrando el valor de esfuerzos de optimización, las herramientas de benchmarking de base de datos siguen siendo indispensables para excelencia en ingeniería de base de datos.