1 puntos por GN⁺ 2024-02-18 | 1 comentarios | Compartir por WhatsApp

Mis notas sobre el diseño del esquema Postgres de GitLab

  • Al revisar el esquema de Postgres de GitLab, quería compararlo con el que diseño yo y aprender buenas prácticas a partir de su definición de esquema.
  • GitLab es una plataforma DevOps de código abierto, una alternativa a GitHub, y se puede autoalojar.

Usar el tipo correcto de clave primaria

  • Cuando la base de datos es pequeña esto no se nota, pero a medida que crece la clave primaria impacta en el espacio de almacenamiento, la velocidad de escritura y la velocidad de lectura.
  • GitLab usa bigserial como tipo de clave primaria en 380 de sus 573 tablas, serial4 en 170 y claves primarias compuestas en las 23 restantes.

Uso de IDs internos y externos

  • Es una buena práctica no exponer la clave primaria al mundo exterior.
  • GitLab usa tanto ID interno (id) como ID externo (iid) en tablas como issues, ci_pipelines, deployments y epics.

Usar el tipo text y restricciones de validación

  • El esquema de GitLab usa tanto character varying(n) como text, pero utiliza más frecuentemente text.
  • text no tiene una restricción de longitud, y define las restricciones de longitud con CHECK.

Convenciones de nomenclatura

  • Todas las tablas usan plural y utilizan el prefijo del nombre del módulo para proporcionar un namespace.
  • Los nombres de tablas y columnas siguen el formato snake_case.

Uso de zonas horarias en timestamps

  • GitLab usa tanto timestamp with timezone como timestamp without timezone.
  • Utiliza timestamp without timezone para operaciones del sistema y timestamp with timezone para acciones de usuario.

Restricciones de clave foránea

  • GitLab usa restricciones de clave foránea en la mayoría de las tablas, aunque hay algunas en las que no las usa, como audit_events, abuse_reports, web_hooks_logs y spam_logs.

Particionamiento de tablas grandes

  • GitLab particiona tablas que podrían crecer para mejorar el rendimiento de las consultas.

Soportar búsquedas LIKE con trigrams y gin_trgm_ops

  • GitLab usa índices GIN (Generalized Inverted Index) para realizar búsquedas de forma eficiente.

Uso de jsonb

  • El esquema de GitLab usa el tipo de dato jsonb en varias tablas.

Otros consejos

  • Usa campos de auditoría como updated_at en tablas que pueden modificarse y no los usa en tablas de logs que no se pueden modificar.
  • Los enums se guardan como smallint en lugar de character varying, lo que ahorra espacio.

Opinión de GN⁺:

  • El diseño del esquema de GitLab ofrece ideas de diseño de base de datos y contiene lecciones importantes para la optimización de esquemas en sistemas de gran escala.
  • Como GitLab es de código abierto, estas decisiones de diseño de esquema ofrecen ejemplos prácticos que otros desarrolladores pueden aplicar en sus propios proyectos.
  • Lo que se puede aprender del esquema de GitLab es que elementos como la selección del tipo de dato, la estrategia de indexación, el particionamiento y el uso de restricciones de clave foránea impactan de forma importante en el rendimiento y mantenimiento de la base de datos.

1 comentarios

 
GN⁺ 2024-02-18
Opiniones de Hacker News
  • No exponer la clave primaria al exterior suele ser una buena práctica. Esto es especialmente importante al usar identificadores enteros o bigint de autoincremento secuencial, porque son predecibles.

    • Se plantea que ocultar la clave primaria al exterior es una buena práctica. En particular, los identificadores enteros de incremento secuencial son predecibles, por lo que esto cobra aún más importancia.
  • Por ejemplo, GitHub tenía 128 millones de repositorios públicos en 2020. Si asumimos 20 issues por repositorio, se pasa el rango de serial. Además, cambiar el tipo de una tabla es costoso.

    • Con el número de repositorios públicos de GitHub y el total estimado de issues se señala que podría superarse el rango serial, y se menciona que cambiar el tipo de una tabla tiene un costo alto.
  • El argumento sobre el tamaño de almacenamiento de una columna UUID no es muy convincente. En una tabla con 5 columnas adicionales, 128 bits versus 64 bits no hace una gran diferencia.

    • Se argumenta que el problema principal es más el rendimiento que el tamaño de almacenamiento de una columna UUID. Señala que UUIDv4 es totalmente aleatorio y no es ideal para el rendimiento de índices, y menciona que UUIDv7 podría ser una mejor solución.
  • A menudo se repite que las claves foráneas son costosas, pero es una afirmación casi nunca verificada. Usar la base de datos requiere conocimiento y experimentación más que reimplementarla, y a menudo trae mejores resultados.

    • Se cuestiona el argumento común de que las claves foráneas son caras y se enfatiza que es importante aprovechar la base de datos adecuadamente.
  • Me gustaría saber si alguien escribió o destacó algo sobre la diferencia de rendimiento entre GitLab y GitHub.

    • Expresa interés en la brecha de rendimiento entre GitLab y GitHub y siente que las cargas de página de GitLab son claramente más lentas que las de GitHub.
  • Tenía curiosidad sobre el propósito de la I adicional en las variables CI_PIPELINE_IID y CI_MERGE_REQUEST_IID. Sospechaba que se debía a una decisión de base de datos, y este artículo lo confirma.

    • Muestra curiosidad por el motivo de la I extra que aparece en variables de CI y concluye que se trata de una decisión relacionada con la base de datos.
  • Este artículo fue de gran utilidad. Me pregunto dónde encontrar otro texto similar.

    • Menciona que le pareció muy útil y que está interesado en encontrar otro material con contenido parecido.
  • ¿Soy el único que piensa que el diseño de esquema y el desarrollo están rezagados para esta época?

    • Siente que el diseño de esquema y el desarrollo se sienten anticuados, y en especial nota riesgo de pérdida de datos durante las migraciones. También cuestiona por qué la base de datos/ORM no maneja automáticamente un ID externo y uno interno.
  • 1 gyeong equivale a 10^16.

    • Se destaca la realidad de tener que elegir entre enteros de 32 y 64 bits, y se menciona la necesidad de un tipo entero de 5 bytes para soportar una cardinalidad de alrededor de 1 billón (10^12).
  • Al usar el tipo nativo UUID v4 de Postgres, el tamaño de la tabla aumenta un 25% y la velocidad de inserción cae al 25% en comparación con bigserial.

    • Muestra curiosidad por la diferencia de rendimiento entre UUIDv4 y bigserial, y pide una explicación de por qué UUIDv4 muestra peores resultados de rendimiento.