Proyecto del Billón de Tablas - PgDay Ecuador 2013
-
Upload
nosys -
Category
Technology
-
view
349 -
download
0
description
Transcript of Proyecto del Billón de Tablas - PgDay Ecuador 2013
El Proyecto del Billón de Tablas
Álvaro Hernández Tortosa <[email protected]>
Acerca de mí
● Álvaro Hernández Tortosa <[email protected]>● Fundador y Director Técnico en NOSYS● ¿Qué hacemos en NOSYS?
✔ Formación, consultoría y desarrollo de software con PostgreSQL (y Java)✔ Partners de EnterpriseDB✔ Formación avanzada en Java con Javaspecialists.eu: Java Master Course y Java Concurrency Course✔ Partners de Amazon AWS. Formación y consultoría en AWS
● Twitter: @ahachete● LinkedIn: http://es.linkedin.com/in/alvarohernandeztortosa/
¿Qué es una base de datos “grande”?
● Bases de datos de un sólo nodo: hasta TBs o decenas de Tbs. Miles de millones a billones de registros.
● Bases de datos multi nodo, virtualmente ilimitadas. Casos conocidos de centenares de TBs e incluso Pbs.
● Esta charla no es acerca de Big Data. Es sólo de Big Data
● De hecho, aquí realmente hablamos de Big MetaData(y el peor ratio metadata/data de la historia)
Tipos de bases de datos (por número de tablas)
Base de datos # Tablas
SLST Schema-Less-Like, Single-Table 1
EDNECRM Extremely De-Normalized Enterprise CRM 2
S Small 20
M Medium 80
L Large 200
XL Extra Large 1,000
ORMGW ORMs Gone Wild 5,000
MT Multi-Tenancy 50,000
MMT Massive Multi-Tenancy 1,000,000
BTP Billion Tables Project 1,000,000,000
Tipos de bases de datos (II)
SLST ENNECRM S M L XL ORMGW MT MMT BTP0
10
20
30
40
50
60
70
80
90
100
Number of tables by database type
10
log
_1
0 (
# ta
ble
s)
Límites teóricos de PostgreSQL
Característica Límite
# columnas / tabla 250-1600 (dependiendo del tipo de las columnas)
Max tamaño / columna 1GB
Max tamaño fila 1.6 TB
Max # filas / tabla ilimitado
Max tamaño / tabla 32 TB
Max # tablas / bbdd ilimitado
Max tamaño / bbdd ilimitado
Dónde empezó todo...
● En 2002, un mail a [email protected]:
“I'm guessing that the maximum number of tables is related to how much can be stored in the pg_ tables […]. So, based on that, the maximum number of rows is unlimited and the maximum size for a table is 64 TB. So realistically, you would need an enormous number (trillions) of tables to exceed that limit”
Simon Cawleyhttp://www.postgresql.org/message-id/53386E0C47E7D41194BB0002B325C997747F2B@NTEX60
Dónde empezó todo... (II)
http://it.toolbox.com/blogs/database-soup/one-billion-tables-or-bust-46270
21 de Mayo de 2011
¿Por qué hacer 1BT?
Ofc
ialm
ente
...
En rea
lidad
...
● Demostrar que PostgreSQL no? tiene límite en el # tablas
● Someter a Postgres a stress de forma no habitual
● Probar un nuevo servidor antes de producción
● Para ganar a Josh Berkus, creando tablas más rápido que él
● “Yo la tengo más grande que tú” (la bbdd)
● Porque podemos
Redefiniendo “tps”
Wikipedia (http://en.wikipedia.org/wiki/Transactions_per_second):
“Transactions Per Second refers to the number of atomic actions performed by certain entity per second”
En lo sucesivo, en esta presentación, querrá decir:
“tablas por segundo”
Primeros intentos (2011)
● Josh Berkus(http://it.toolbox.com/blogs/database-soup/one-billion-tables-or-bust-46270): 3M tablas, 83 tps. PostgreSQL murió (sin disco). Serial + text
● Jan Urbanski(http://it.toolbox.com/blogs/database-soup/one-billion-tables-part-2-46349): 4.6M tablas, 1K tps. PostgreSQL murió (inodes). Int + text
● $SELF(http://it.toolbox.com/blogs/database-soup/one-billion-tables-part-2-46349): 10M tablas, 2K2 tps. Finalziación correcta. 1 columna int100M tablas, 1K5 tps. Finalziación correcta. 1 columna int
100M tablas. ¿Cómo lograrlo?
● Necesitamos RAM:Out of memory: kill process 4143 (postgres) score 235387 or a childKilled process 4146 (postgres)
● Un sistema de ficheros que pueda manejar muchos ficheros: reiserfs
● Estrategia de creación de tablas:➔ No usar un fichero CSV o .sql pre-generado➔ No usar un driver a través de TCP/IP➔ Solución: enviar comandos SQL vía la entrada
estándar, con psql sobre sockets UNIX
100M tables. How to get there? (II)
Configurar postgresql.conf:
fsync = ofsynchronous_commit = offull_page_writes = ofwal_bufers = 256MBautovacuum = ofmax_locks_per_transaction = 10000shared_bufers = 16384MBcheckpoint_segments = 128
100M tables. How to get there? (III)
Primer servidor probado:
● Intel Core 2 CPU● 4GB RAM● 3X 1TB SATA 7K2 rpm, RAID 0● Reiserfs● Ubuntu 10.04● PostgreSQL 9.0
100M tablas. El código
100M tablas. Los resultados
510
1520
2530
3540
4550
5560
6570
7580
8590
95100
0
500
1000
1500
2000
2500
3000
100M tables
Intel Core 2, 4GB RAM, 3TB reiser
time (min)
speed (tps)
M tables
Uso de disco: 257GB
El camino a 1B tablas. Los peores enemigos
● Autovacuum(¿pero no estaba autovacuum = of ?)
autovacuum_freeze_max_age = 2000000000# maximum XID age before forced vacuum
● updatedb(¿quién activa esto por defecto en las distros??????)
El camino a 1B tablas. El almacenamiento
● Separar el directorio base del directorio de tablas
● Crear un tablespace (o más) en una partición reiserfs (llamada /data)
● El mejor rendimiento se obtuvo con base en XFS (/bigdata). El patrón es añadir, como una bbdd “normal”
● Los registros de WAL van a RAM (tmpfs con swap para evitar desbordamientos, montado en /xlog)
El camino a 1B tablas. El almacenamiento (II)
El camino a 1B tablas. Tablespaces
● Excepto reiserfs, otros sistemas de ficheros degradan rápidamente con el número de ficheros
● Incluso reiser pierde rendimiento con varios millones
● Solución: crear tantos tablespaces como sea necesario (incluso dentro del mismo sistema de ficheros)
● Para la prueba de 1B, usamos 1000 tablespaces para máximo rendimiento
El camino a 1B tablas. Una pizza más grande
● 2X Intel(R) Xeon(R) CPU E5-2650 @ 2.00GHz(16 cores, 32 threads)
● 48GB RAM
● Versión moderna de SO y Postgres:➔ Debian wheezy (kernel 3.2.41)➔ PostgreSQL 9.2.4
● Apenas unos segundos para hacer “make -j16” postgresql
El camino a 1B tablas.. Concurrencia
● La creación de tablas no limita por disco. El rendimiento medio fue de < 5MB/s en la prueba de 100M tablas
● Hay dos límites principales:➔ La velocidad de la CPU (los backends alcanzan el 100% si se ejecutan aisladamente)➔ La contención (locking)
● Para mejorar el rendimiento, lanzamos varios procesos en segundo plano
● 16 procesos fue la mejor combinación
El camino a 1B tablas. Concurrencia (II)
● Con múltiples procesos, no podemos permitir que cada proceso loguee sus propios datos (por la dificultad de agregar los datos)
● Ejecutamos otro proceso sólo para loguear los datos:➔ El logger tiene el PID de cada trabajador➔ Cuando el logger quiere loguear, envía una señal SIGUSR1 a los trabajadores➔ El logger espera la información en un fifo identificado por el PID del trabajador➔ El trabajador escribe el número de tablas que ha generado hasta la fecha
El camino a 1B tablas. El código
● El trabajador es un script en python:➔ Divide en interaciones el número de tablas asignado➔ En cada iteración, crea un proceso psql al que le manda el comando CREATE TABLE … TABLESPACE … a través de la entrada estándar➔ Cuando recibe la señal USR1, escribe el número de tablas actual al fifo➔ Sale cuando recibe (del logger) la señal TERM➔ Las iteraciones (I/O) se ejecutan en un thread
● El logger es un shell script que loguea cuando recibe USR1● Main es también un shell script. Lanza todos los procesos y manda al logger que loguee cada 10s (le manda USR1)
El camino a 1B tablas. El código (II)
btp-main.sh
btp-process.py
btp-logger.sh
1B tablas. ¿Funcionó?
$ time ./btp-main.sh 1000000000 16 50000 1000real 2022m19.961suser 240m7.044ssys 165m25.336s(esto es: 33h 42m 20s)
● Media: 8242tps
btp=# SELECT txid_current(); txid_current -------------- 1000001685
1B tablas. ¿Funcionó? (II)
$ echo -e '\\timing on\nSELECT count(*) FROM pg_class' |psql btp count------------ 1000000288Time: 9221642.102 ms
$ df -h /data /bigdata /var/tmpFilesystem Size Used Avail Use% Mounted on
/dev/mapper/vgMain-data 500G 97G 404G 20% /data
/dev/etherd/e15.0 5.5T 2.6T 3.0T 46% /bigdata
tmpfs 90G 4.1G 86G 5% /var/tmp
1B tablas. ¿Funcionó? (III)
btp=# SELECT relname, heap_blks_read, heap_blks_hit, idx_blks_read, idx_blks_hit FROM pg_statio_all_tables WHERE relname IN ('pg_tablespace', 'pg_database', 'pg_shdepend');
relname | heap_blks_read | heap_blks_hit | idx_blks_read | idx_blks_hit
---------------+----------------+---------------+---------------+--------------
pg_tablespace | 35 | 6226009368 | 13 | 6794
pg_database | 3 | 63015 | 12 | 105017
pg_shdepend | 1 | 1000001001 | 5 | 1001537778
btp=# INSERT INTO _3ade68b1 VALUES (2), (3);
Time: 20.673 ms
btp=# SELECT * FROM _3ade68b1 LIMIT 1;
[...]
Time: 0.207 ms
1B tablas. ¿Cuánto tiempo requiere un “\dt”?
$ time ./postgresql-9.2.4/bin/psql btp -c "\dt" > tables
∞ERROR: canceling statement due to user request
real 2993m51.710s
user 0m0.000s
sys 0m0.000s
Terminado vía pg_cancel_backend()
1B tablas. Rendimiento
2080
200260
300320
340380
440460
540600
620640
680860
1000
0
2000
4000
6000
8000
10000
12000
1B tables. Performance
Tables per second
tps
M tables
Pico: 10Ktps
1B tablas. Rendimiento (II)
Carga media de los backends: 57%Carga media del sistema: 11.7
2080
200260
300320
340380
440460
540600
620640
680860
1000
05000
1000015000200002500030000350004000045000
1B tables
Memory usage
mem free (MB)
buffers (MB)
Cached (MB)
M tables
Restaurando la durabilidad de la bbdd
● Detener el servidor y llevar pg_xlog a disco de nuevo
● Configurar postgresql.conf:
fsync = onsynchronous_commit = onfull_page_writes = onautovacuum = of
● Reiniciar el servidor. Y disfrutar :)
El camino a... 2B de tablas
● Una pizza aún mayor 2x Xeon quad-core de última generación a 3.3 Ghz➔ Más rápido que 16-core 2.0Ghz (8K5tps @100Mt):
✔ Con 16 procesos: 11K9 tps @100Mt✔ Con 8 procesos: 12K3 tps @100Mt
$ time ./btp-main.sh 1000000000 8 50000 1000real 1400m6.680suser 165m32.565ssys 119m46.493s(esto es: 23h 20m 07s)Media: 11903tps
El camino a... 2B de tablas (II)
● Necesidades de almacenamiento:➔ Base: ~6TB➔ Tablespaces: ~ 300GB
● El problema de autovacuum (otra vez):➔ autovacuum_freeze_max_age como máximo es
2E9➔ Autovacuum se lanzará. Si los matamos, postgres
los relanza➔ Antes hacíamos una tabla por transacción➔ Si agrupamos varias tablas creadas por
transacción, el rendimiento baja (curioso)
¿Qué tablas de catálogo escribe CREATE TABLE?
● Para una tabla de 1 columna, sin índices:➔ 1 entrada en pg_class➔ 2 entradas en pg_type (el tipo de la tabla y el tipo del array de tabla)➔ 3 entradas en pg_depend (2 para los tipos, 1 para el schema al que pertenece la tabla)➔ 7 entradas en pg_attribute (xmin, xmax, cmin, cmax, ctid, tableoid y la propia columna)
➔ Así que crear 11K9 tablas realmente quiere decir:➔ Hacer 154K inserciones por segundo➔ Más 11K9 fcheros creados por segundo(1MB/s de metainformación)
Entonces, ¿hay algún límite en el número de tablas?
● Tanto pg_class como pg_type tienen columnas oid
● Los oids son enteros de 32 bits sin signo
● Para cada tabla creada, se insertan 2 registros en pg_type
● Hay 330 tipos por defecto en 9.2
● Por lo tanto, hay un límite en el número máximo de tablas: (2^32 – 330) / 2 = 2_147_483_483
(2_147_483_481 en 9.3)
Validando empíricamente la teoría
● Objetivo: intentar crear 2_147_483_481 tablas en pg9.3
● Llegados allí, intentar crear una tabla más :)
● Hemos usado Amazon AWS para ello. Una instancia cr1.8xlarge (16 cores, 244GB RAM, 2x120GB SSD)
● Los tablespaces estaban en un RAID0 de los 2 SSDs
● Tablas de catálogo: RAID0 de 6x volúmenes de 1TB IOPSs no garantizados
Validando empíricamente la teoría: los costes
Amazon aportó créditos para la realización de estas pruebas. ¡Muchas gracias, Amazon!
$1,877.23
Validando empíricamente la teoría: las tablas
Validando empíricamente la teoría: las tablas (II)
Validando empíricamente la teoría: el resultado
2,147,475,456 tablas
(a 8025 del límite teórico)
Agradecimientos
● A Josh Berkus (y Selena Deckelmann, Jan Urbanski y Álvaro Herrara) que son los locos inventores de esta idea
● Grandes agradecimientos a José Luis Tallón:➔ Por proveer del hardware inicial y tunearlo
➔ Por co-crear, co-programar, co-organizar y co-disfrutar este proyecto conmigo
● A ASLE, patrocinadores del evento, PostgreSQL Global y especialmente a Jaime Casanova por el esfuerzoen trarme acá :)
El Proyecto del Billón de Tablas
Álvaro Hernández Tortosa <[email protected]>