curso
Contratos de datos desmitificados: Todo lo que necesitas saber
Los contratos de datos son la columna vertebral de la calidad de los datos y la escalabilidad de las soluciones de datos distribuidos. Especifican el formato, el esquema y los protocolos que rigen el intercambio entre las entidades de la base de datos. Estos acuerdos formales eliminan las ambigüedades y las suposiciones no documentadas sobre los datos.
En este artículo, aclararé el concepto de contrato de datos ofreciendo técnicas básicas y avanzadas para facilitar su aplicación efectiva.
Comprender los Contratos de Datos
Un único contrato de datos delinea los parámetros precisos para el intercambio de datos entre dos modelos. Estos acuerdos formales garantizan que no haya ambigüedades sobre el formato y los esquemas de los datos.
Las definiciones y la validación de los contratos de datos son cruciales para una colaboración eficaz entre equipos.
En pocas palabras, un contrato de datos es un acuerdo formal entre el proceso que cambia el estado original de nuestros datos (productores) y los destinos (consumidores). Es muy parecido a cómo funcionan los contratos comerciales. Representan obligaciones entre proveedores y consumidores de un producto empresarial. Los contratos de datos hacen lo mismo con los productos de datos, es decir, tablas, vistas, modelos de datos, etc.
El objetivo es mitigar las interrupciones en el flujo descendente de datos y hacer que las transformaciones de datos sean estables y fiables.
Los principales componentes de un contrato de datos son el esquema (columnas y formatos), la parte de la capa semántica (medidas, cálculos y restricciones), los acuerdos de nivel de servicio (SLA) y la gobernanza de los datos.
Los beneficios de los contratos de datos incluyen:
- Automatización de la calidad de los datos y comprobaciones cuando se crean o actualizan nuevas salidas de datos.
- Permitir un escalado eficaz, especialmente para la arquitectura de datos distribuidos, por ejemplo, la malla de datos.
- Mejorar el ciclo de vida del desarrollo de datos, centrándose en la creación de herramientas para la validación de contratos.
- Fomentar la colaboración mediante la retroalimentación entre productores y consumidores de datos.
Contratos de datos. Imagen del autor.
Ejemplo de contrato de datos con dbt
En un contrato de datos, los esquemas definen los nombres de los atributos, los tipos de datos y si los atributos son obligatorios. También pueden especificar el formato, la longitud y los rangos de valores aceptables para las columnas.
Consideremos un esquema de modelo dbt definido como sigue en un archivo YAML. Nuestro esquema de tablas está definido en columns
:
models:
- name: dim_orders
config:
materialized: table
contract:
enforced: true
columns:
- name: order_id
data_type: int
constraints:
- type: not_null
- name: order_type
data_type: string
Ahora imaginemos que definimos así nuestro modelo dim_orders
:
select
'abc123' as order_id,
'Some order type' as order_type
Tener un contract
como enforced: true
en nuestra definición del modelo provocará el siguiente error si intentamos materializar dim_orders
en una tabla de nuestra plataforma de datos:
20:53:45 Compilation Error in model dim_customers (models/dim_orders.sql)
20:53:45 This model has an enforced contract that failed.
20:53:45 Please ensure the name, data_type, and number of columns in your contract match the columns in your model's definition.
20:53:45
20:53:45 | column_name | definition_type | contract_type | mismatch_reason |
20:53:45 | ----------- | --------------- | ------------- | ------------------ |
20:53:45 | order_id | TEXT | INT | data type mismatch |
20:53:45
20:53:45
20:53:45 > in macro assert_columns_equivalent (macros/materializations/models/table/columns_spec_ddl.sql)
Lo mismo habría ocurrido con las columnas adicionales, las comprobaciones de SLA y los metadatos que faltan, si hubiéramos decidido definirlos.
Un ejemplo dbt más avanzado contendría restricciones de modelo forzadas:
# models/schema.yaml
models:
- name: orders
# required
config:
contract:
enforced: true
# model-level constraints
constraints:
- type: primary_key
columns: [id]
- type: FOREIGN_KEY # multi_column
columns: [order_type, SECOND_COLUMN, ...]
expression: "OTHER_MODEL_SCHEMA.OTHER_MODEL_NAME (OTHER_MODEL_FIRST_COLUMN, OTHER_MODEL_SECOND_COLUMN, ...)"
- type: check
columns: [FIRST_COLUMN, SECOND_COLUMN, ...]
expression: "FIRST_COLUMN != SECOND_COLUMN"
name: HUMAN_FRIENDLY_NAME
- type: ...
columns:
- name: FIRST_COLUMN
data_type: DATA_TYPE
# column-level constraints
constraints:
- type: not_null
- type: unique
- type: foreign_key
expression: OTHER_MODEL_SCHEMA.OTHER_MODEL_NAME (OTHER_MODEL_COLUMN)
- type: …
Proporcionar una definición de esquema como conjunto de reglas y restricciones aplicadas a las columnas de un conjunto de datos ofrece información muy importante para procesar y analizar los datos.
Los esquemas tienden a cambiar con el tiempo.
Se trata de una situación habitual. Imaginemos que nuestra tabla de origen añade una columna extra contraída:
select
'abc123' as order_id,
'Some order type' as order_type,
'USD' as currency
Es esencial tener en cuenta los cambios de esquema al realizar actualizaciones incrementales porque, de lo contrario, la salida del modelo incremental posterior invalidaría el contrato.
Esto puede solucionarse añadiendo on_schema_change: append
a la estrategia incremental dbt.
Las validaciones de esquemas pueden ser explícitas o implícitas.
Algunos formatos de archivo de big data, como AVRO y Parquet, admiten por defecto definiciones de esquema incorporadas e implícitas, por lo que no es necesaria una validación externa adicional.
Por el contrario, los formatos de archivo de datos sin esquema, como JSON, requieren una validación externa del esquema. Algunas bibliotecas de Python, como pydantic
o una simple @dataclass
, pueden realizar esto:
from pydantic import BaseModel
class ConnectionDataRecord(BaseModel):
user: str
ts: int
record = ConnectionDataRecord(user="user1", ts=123456789)
Si infringimos las normas y asignamos valores que no se ajustan a nuestros criterios, se lanzará una excepción. Por ejemplo, se producirá una excepción si intentamos llamar a ConnectionDataRecord('', 1)
.
Contratos de datos semánticos
Las validaciones de datos semánticos garantizan que los datos son lógicamente coherentes y se alinean con la lógica empresarial.
Las validaciones semánticas deben aplicarse explícitamente.
De hecho, a diferencia de las comprobaciones de esquemas, los contratos semánticos de datos dependen de la lógica empresarial y deben implementarse externamente.
La semántica en muchos escenarios de casos de uso parece una extensión de los contratos validados por esquema. A menudo, depende de reglas empresariales y representa un conjunto de condiciones de fila que nuestro modelo de datos debe cumplir.
Un ejemplo de contrato semántico puede ser el siguiente:
- Desviación métrica: de la media móvil o de cualquier otro umbral. De hecho, podemos vivir con que el número de usuarios activos de ayer caiga por debajo del 75% de la media móvil de 7 días, pero no toleraremos el 0%.
- Lógica empresarial: Alertas de supervisión de transacciones y puntuaciones de prevención del fraude. En este caso, el pago debe ser 0.
- Linaje de los datos: Describe cómo evolucionan las entidades de datos. Por ejemplo,
transaction_completed_at
no puede ocurrir antes quecreated_at
. - Integridad referencial: Las relaciones entre entidades son importantes y también pueden describirse mediante contratos semánticos. Considera el código dbt que aparece a continuación. Explica que la dirección
refund_id
de cada devolución corresponde a una direccióntransaction.id
válida.
- name: refunds
enabled: true
description: An incremental table
columns:
- name: refund_id
tests:
- relationships:
tags: ['relationship']
to: ref('transactions')
field: id
Corresponde al usuario final establecer el nivel de alerta en los contratos semánticos, y esto a menudo se implementa con pruebas de calidad de datos personalizadas.
Varias reglas de lógica empresarial se refieren a menudo a la integridad de los datos. Los escenarios de datos ilógicosal pueden surgir de errores en las configuraciones de la base de datos y el servidor o de la inyección involuntaria de datos de prueba en el entorno de producción. Las comprobaciones de integridad de los datos están diseñadas para validar los datos con respecto a esas normas empresariales, ayudando a identificar los valores que no parecen correctos o son ilógicos.
Las entidades de la base de datos siempre se relacionan entre sí. Esto se denomina relación entidad y suele presentarse mediante un diagrama entidad relación (ERD). Una integridad referencial inadecuada puede provocar problemas como datos incompletos o ausentes. Los contratos de datos deben abordar estos posibles escollos para garantizar la integridad y exactitud de los datos.
Por ejemplo, una relación habitual es una asociación de uno a muchos entre customers
y orders
, en la que un mismo cliente puede tener varios orders.
. En este caso, un pedido sólo se considera válido si contiene un customer_id
válido dentro del conjunto de datos customers
.
Este tipo de restricción, una restricción de integridad referencialgarantiza que la relación entre entidades se mantiene con precisión.
Acuerdos de Nivel de Servicio (ANS) en los Contratos de Datos
Los SLA son un nivel adicional de comprobación de la calidad de los datos que puede aplicarse mediante contratos de datos.
Los ANS se refieren a la frescura de los datos.
Dado que los modelos de datos se actualizan periódicamente con nuevos datos, los ANS pueden incluir comprobaciones sobre el plazo máximo en que se espera que estén disponibles los nuevos datos o el retraso máximo admisible. Por ejemplo, en dbt, puede conseguirse utilizando pruebas de frescura:
- name: orders
enabled: true
description: A source table declaration
tests:
- dbt_utils.recency: # https://github.com/dbt-labs/dbt-utils#recency-source
tags: ['freshness']
datepart: day
field: timestamp
interval: 1
Supongamos que queremos generar un informe sobre los hechos de ayer; para ello, queremos asegurarnos de que los datos existen. De hecho, sería extraño no ver los nuevos pedidos durante unos días o más.
En el ejemplo siguiente, podemos probar nuestro conjunto de datos para detectar retrasos inesperados en los pedidos utilizando la configuración de prueba en dbt. Esto te permite seleccionar y hacer referencia a la prueba utilizando ese nombre específico.
version: 2
models:
- name: orders
columns:
- name: status
tests:
- accepted_values:
name: unexpected_order_status_today
values: ['placed', 'shipped', 'completed', 'returned']
config:
where: "order_date = current_date"
Al definir un nombre personalizado, obtienes un control total sobre cómo se muestra la prueba en los mensajes de registro y en los artefactos de metadatos.
Del mismo modo, en los conductos de datos en tiempo real, normalmente se espera que los datos no tengan más de unas horas de antigüedad. Los SLA son cruciales para las aplicaciones de procesamiento de flujos, en las que los datos se procesan en tiempo real con minutos o incluso segundos de latencia.
En las aplicaciones de streaming, queremos comprobar el retraso máximo permitido para los eventos que llegan tarde y métricas como el Tiempo Medio Entre Fallos (MTBF) y el Tiempo Medio de Recuperación (MTTR). Implementar esto implica hacer un seguimiento meticuloso de los incidentes y extraer los datos relevantes de las herramientas de supervisión de aplicaciones y gestión de incidentes, como PagerDuty, Datadog y Grafana.
Contratos de Gobernanza de Datos
Manejar correctamente la Información de Identificación Personal (IIP) forma parte integral del proceso de transformación de datos. Para muchas empresas, es crucial que estos conjuntos de datos sean al menos conformes con el GDPR y se adhieran a normativas de privacidad de datos como HIPAA o PCI DSS.
Los contratos de gobernanza de datos garantizan una seudonimización o enmascaramiento de datos adecuadas.
Considera el código dbt que aparece a continuación. Los contratos ejecutados como tests
requieren que user_email
sea un hash SHA256 (enmascarado):
models:
- name: customer_data
columns:
- name: user_email
tests:
- dbt_expectations.expect_column_values_to_not_match_regex:
regex: "^(?!.*\b@\b).* # Ensure identifiers do not contain emails
flags: i # Case-insensitive matching
Por otro lado, puede que queramos aplicar la concordancia de patrones a otras tablas. Por ejemplo, en el ejemplo siguiente, el campo transaction_reference
debe seguir el patrón [“TRX-%”, “%-2023”]
:
models:
- name: transaction_data
columns:
- name: transaction_reference
tests:
- dbt_expectations.expect_column_values_to_match_like_pattern_list:
like_pattern_list: ["TRX-%", "%-2023"]
match_on: any
Los contratos de gobernanza de datos también pueden ser beneficiosos cuando incluyen columnas con datos sensibles, metadatos (propietarios de los datos, etc.) y funciones de los usuarios autorizados a acceder a un producto de datos.
Por ejemplo, podemos indicar el propietario de nuestro modelo de datos y la fase del ciclo de vida de desarrollo del modelo utilizando el campo meta
de dbt:
# models/schema.yaml
version: 2
models:
- name: users
meta:
owner: "@data_mike"
model_maturity: in dev
contains_pii: true
columns:
- name: email
meta:
contains_pii: true
El campo meta
te permite establecer metadatos para un recurso, que luego se compilan en el archivo manifest.json
generado por dbt y pueden verse en la documentación generada automáticamente.
Podemos utilizar paquetes como dbt-checkpoint para escanearlo durante el pull request y asegurarnos de que nuestros meta campos obligatorios están presentes. El gancho falla si algún modelo (de un manifiesto o de archivos YAML) no tiene las meta claves especificadas.
Las claves meta
del modelo deben estar en el archivo YAML o en el manifiesto.
Patrones de Implementación de Contratos de Datos
La validación de contratos se puede realizar en los conductos de datos de flujo (por fila) antes de que se ingieran los datos y después de ellos, en la fuente (capa del modelo de datos de origen).
Cuando ingerimos los datos "tal cual", el proceso de validación actúa como un paso de transformación, aplicando las reglas del contrato y filtrando los datos no válidos, es decir, a una vista de la base de datos dedicada o a una tabla donde los datos pueden investigarse más a fondo.
Las comprobaciones de validación pueden aplicarse a posteriori cuando los datos se ingieren directamente en un lago de datos sin procesar.
La principal ventaja de la validación de contratos de datos en tiempo real es su capacidad para filtrar los registros no válidos antes de que lleguen a su destino final: un lago de datos o un almacén de datos. Este enfoque es frecuente en el procesamiento de datos basado en eventos o en tiempo real, como los eventos de Captura de Datos de Cambios (CDC). En este tipo de validación, ciertos aspectos del contrato se verifican a medida que los datos fluyen por la tubería.
Herramientas para Contratos de Datos
La comunidad de datos está reconociendo gradualmente los beneficios potenciales de los contratos de datos, un área de la ingeniería de datos en constante evolución. Existen muchas herramientas en este espacio, algunas todavía en sus primeras fases. dbt puede considerarse un marco universal para los contratos de datos.
Se pueden implementar contratos similares utilizando el Dataform de Google en origen (capa del modelo de datos de origen), es decir, cuando los datos se han ingestado correctamente en nuestro almacén de datos. Para ello deberíamos utilizar condiciones de fila simples.
Considera el siguiente ejemplo. Aplica determinadas condiciones de fila para nuestra tabla:
-- my_table.sqlx
config {
type: "table",
assertions: {
nonNull: ["user_id", "customer_id", "email"]
}
}
SELECT …
A continuación se muestra otro ejemplo de implementación de un contrato de datos, que puede lograrse utilizando Soda.io, un marco de calidad de datos especializado:
# Checks for basic validations
checks for dim_customer:
- row_count between 10 and 1000
- missing_count(birth_date) = 0
- invalid_percent(phone) < 1 %:
valid format: phone number
- invalid_count(number_cars_owned) = 0:
valid min: 1
valid max: 6
- duplicate_count(phone) = 0
Ajustar la configuración de alertas te permite configurar una comprobación para que emita una advertencia en lugar de fallar la validación. Un escaneado Soda ejecuta las comprobaciones especificadas en un acuerdo, comprueba el archivo YAML o en línea dentro de una invocación programática, y devuelve un resultado por cada comprobación: aprobado, suspenso o error.
Según mi experiencia, la introducción de los contratos de datos en muchas empresas sigue siendo fragmentaria, dependiendo de factores como los patrones de diseño de las canalizaciones de datos (por lotes o en tiempo real), las opciones de serialización de los datos y los sistemas utilizados para el almacenamiento y el procesamiento.
La aplicación del contrato de datos depende de los requisitos y la lógica de la empresa.
Great Expectations, una biblioteca de Python, puede utilizarseed para implementar contratos de datos a nivel semántico. Se puede instalar mediante pip: pip install great_expectations
.
Después de ejecutar great_expectations init
, podemos proceder a la validación de los datos:
Using v3 (Batch Request) API
___ _ ___ _ _ _
/ __|_ _ ___ __ _| |_ | __|_ ___ __ ___ __| |_ __ _| |_(_)___ _ _ ___
| (_ | '_/ -_) _ | _| | _|\ \ / '_ \/ -_) _| _/ _ | _| / _ \ ' \(_-<
\___|_| \___\__,_|\__| |___/_\_\ .__/\___\__|\__\__,_|\__|_\___/_||_/__/
|_|
~ Always know what to expect from your data ~
Let's create a new Data Context to hold your project configuration.
Great Expectations will create a new directory with the following structure:
great_expectations
|-- great_expectations.yml
|-- expectations
|-- checkpoints
|-- plugins
|-- .gitignore
|-- uncommitted
|-- config_variables.yml
|-- data_docs
|-- validations
OK to proceed? [Y/n]:
Considera el siguiente fragmento de código. Explica cómo crear una definición de comprobación de datos para la columna price
:
"expectation_type": "expect_column_values_to_match_regex",
"kwargs": {
"column": "price",
"mostly": 1.0,
"regex": "^\\$([0-9],)*[0-9]+\\.[0-9]{2}$"
},
Buenas prácticas en la contratación de datos
Aquí no hay una respuesta correcta o incorrecta, ya que, según mi experiencia, el éxito de la implantación de un contrato de datos depende en gran medida de los requisitos de la empresa. Para que los contratos de datos funcionen eficazmente, sigue estas buenas prácticas clave:
- Escalabilidad: Recomiendo añadir mecanismos de extensibilidad (por ejemplo,
on_schema_change: append
) y versionado, que permitirían modificar las condiciones del contrato de datos sin interrumpir las integraciones de canalización existentes. Diseña contratos de datos teniendo en cuenta los cambios futuros y la escalabilidad. Este enfoque garantiza que el contrato pueda adaptarse a la evolución de las necesidades y al crecimiento. - Reglas claras: Recomiendo utilizar un lenguaje directo y conciso en el contrato de datos para evitar malentendidos y malas interpretaciones. El contrato debe redactarse y nombrarse de forma accesible y comprensible para todas las partes implicadas, independientemente de sus conocimientos técnicos.
- Colaboración: El esfuerzo de colaboración garantiza una comprensión exhaustiva y completa de los requisitos, abordando diversas perspectivas y necesidades. Al crear contratos de datos, implica a diversas partes interesadas, como productores de datos, ingenieros de datos, científicos de datos y representantes de los departamentos de negocio, TI, jurídico y de cumplimiento.
- Metadata: Recomiendo proporcionar contratos de datos con documentación y metadatos exhaustivos. Una documentación exhaustiva ayuda a aplicar y mantener el contrato sin problemas. Debe incluir descripciones detalladas, definiciones de campos, reglas de validación y otra información relevante que apoye una comprensión clara y una aplicación eficaz del contrato.
- Revisiones periódicas: La revisión continua ayuda a mantener la relevancia y eficacia del contrato a lo largo del tiempo. Poner en marcha un enfoque estructurado para el seguimiento y la actualización de los contratos de datos. Las revisiones periódicas garantizan que el contrato se mantiene al día, se ajusta a la evolución de los requisitos empresariales y cumple las normativas nuevas o cambiantes.
Conclusión
Recientemente se ha producido un cambio hacia la propiedad distribuida de los datos, en la que los equipos de dominio son responsables de sus productos de datos. Este cambio obligó a las organizaciones a redefinir las expectativas de calidad de los datos, formalizadas mediante contratos de datos.
Las validaciones de datos semánticos garantizan que los datos son lógicamente coherentes y se alinean con la lógica empresarial. Ayudan a comprobar los conductos de datos para detectar cualquier valor atípico en los datos, el valor, el linaje y la integridad referencial. Una integridad referencial inadecuada puede hacer que falten datos o que éstos estén incompletos, por eso también es importante.
Los contratos de gobernanza de datos también pueden implementarse en los pipelines CI/CD y resultan muy útiles cuando indican columnas con datos sensibles, metadatos (propietarios de los datos, etc.) y roles de usuarios autorizados a acceder a un producto de datos.
Los metadatos de un modelo, junto con cualquier otro metacampo obligatorio definido por el desarrollador, ayudan a controlar el uso de recursos y el rendimiento del modelo.
Los Acuerdos de Nivel de Servicio (SLA) de los contratos de datos describen compromisos específicos relacionados con la frescura, integridad y recuperación de fallos de los datos.
Los contratos de datos son esenciales para las técnicas modernas de modelado de datos y ayudan a garantizar que la plataforma de datos sea propensa a errores y escale bien. Resolver los problemas de calidad de los datos puede resultar caro. Para las empresas de nivel empresarial, maximizar el rendimiento de la inversión (ROI ) de los datos es cada vez más importante, aprovechando las herramientas de calidad de datos existentes que apoyan la validación de los contratos de datos.
Preguntas frecuentes
¿En qué se diferencian los contratos de datos de la validación y comprobación de datos?
Los contratos de datos son acuerdos formales que especifican el formato, el esquema y los protocolos de intercambio de los productores y consumidores de datos. Establecen expectativas y responsabilidades claras sobre la calidad de los datos. Por otro lado, la validación y comprobación de los datos son procesos que comprueban si los datos cumplen estas expectativas. La validación garantiza que los datos se ajustan al contrato definido, mientras que la comprobación evalúa la exactitud y fiabilidad de los datos.
¿Pueden utilizarse los contratos de datos en canalizaciones de datos en tiempo real?
Sí, los contratos de datos pueden implementarse en canalizaciones de datos de flujo en tiempo real. Ayudan a filtrar los datos no válidos antes de que lleguen a su destino, garantizando que sólo se procesen los datos que se ajusten a normas y formatos predefinidos. Este enfoque es beneficioso en el procesamiento basado en eventos o en tiempo real, donde la integridad de los datos y la puntualidad son fundamentales.
¿Cómo gestionas el versionado en los contratos de datos cuando los cambios de esquema son frecuentes?
Manejar las versiones en los contratos de datos implica mantener la compatibilidad con versiones anteriores y seguir la evolución del esquema. Un enfoque consiste en utilizar esquemas versionados, en los que cada versión del contrato se asocia a una versión concreta del esquema. Herramientas como on_schema_change: append
en dbt pueden ayudar a gestionar los cambios de esquema sin interrumpir las integraciones existentes, permitiendo transiciones y actualizaciones graduales.
¿Qué papel desempeñan los contratos de datos en la arquitectura de malla de datos?
En una arquitectura de malla de datos, la propiedad de los datos se distribuye entre los equipos de dominio; los contratos de datos garantizan la calidad coherente de los datos y la interoperabilidad entre dominios. Formalizan las expectativas entre productores y consumidores de datos, ayudando a alinear a los equipos en torno a las normas de datos y reduciendo el riesgo de problemas de calidad de los datos a medida que éstos fluyen por distintos dominios.
¿Cómo pueden ayudar los contratos de datos a cumplir normativas de privacidad como el GDPR o la HIPAA?
Los contratos de datos pueden hacer cumplir las políticas de gobernanza de datos, incluidas las normativas de privacidad como el GDPR o la HIPAA. Pueden definir normas para el enmascaramiento de datos, la seudonimización y los controles de acceso, garantizando que los datos sensibles se manejen adecuadamente. Al incorporar estas normas al contrato, las organizaciones pueden automatizar las comprobaciones de cumplimiento y reducir el riesgo de violaciones de la privacidad.
¡Aprende más sobre ingeniería de datos con estos cursos!
programa
Professional Data Engineer
curso
Understanding Modern Data Architecture
blog
5 competencias esenciales en ingeniería de datos
blog
Cómo convertirse en ingeniero de datos en 2023: 5 pasos para el éxito profesional
blog
20 proyectos de análisis de datos para todos los niveles
blog
Las 21 mejores preguntas y respuestas de la entrevista sobre ingeniería de datos
blog
Certificaciones Databricks en 2024: La guía completa
Gus Frazer
24 min
blog