Actualizar datos de tablas con particiones mediante DML
En esta página se ofrece una descripción general de la compatibilidad con el lenguaje de manipulación de datos (DML) en las tablas particionadas.
Para obtener más información sobre DML, consulta:
- Introducción a DML
- Sintaxis de DML
- Actualizar datos de tablas mediante el lenguaje de manipulación de datos
Tablas usadas en los ejemplos
Las siguientes definiciones de esquema JSON representan las tablas que se usan en los ejemplos de esta página.
mytable
: una tabla con particiones por hora de ingestión
[ {"name": "field1", "type": "INTEGER"}, {"name": "field2", "type": "STRING"} ]
mytable2
: una tabla estándar (sin particiones)
[ {"name": "id", "type": "INTEGER"}, {"name": "ts", "type": "TIMESTAMP"} ]
mycolumntable
: una tabla con particiones que se ha particionado mediante la columna ts
TIMESTAMP
[ {"name": "field1", "type": "INTEGER"}, {"name": "field2", "type": "STRING"} {"name": "field3", "type": "BOOLEAN"} {"name": "ts", "type": "TIMESTAMP"} ]
En los ejemplos en los que aparece COLUMN_ID, sustitúyelo por el nombre de la columna en la que quieras realizar la operación.
Insertar datos
Para añadir filas a una tabla con particiones, usa una declaración de DML INSERT
.
Insertar datos en tablas con particiones por hora de ingestión
Cuando usas una instrucción DML para añadir filas a una tabla con particiones por hora de ingestión, puedes especificar la partición a la que se deben añadir las filas. Haces referencia a la partición mediante la pseudocolumna _PARTITIONTIME
.
Por ejemplo, la siguiente instrucción INSERT
añade una fila a la partición del 1 de mayo del 2017 de mytable
— “2017-05-01”
.
INSERT INTO project_id.dataset.mytable (_PARTITIONTIME, field1, field2) SELECT TIMESTAMP("2017-05-01"), 1, "one"
Solo se pueden usar las marcas de tiempo que correspondan a límites de fecha exactos. Por ejemplo, la siguiente instrucción DML devuelve un error:
INSERT INTO project_id.dataset.mytable (_PARTITIONTIME, field1, field2) SELECT TIMESTAMP("2017-05-01 21:30:00"), 1, "one"
Insertar datos en tablas con particiones
Insertar datos en una tabla con particiones mediante DML es lo mismo que insertarlos en una tabla sin particiones.
Por ejemplo, la siguiente instrucción INSERT
añade filas a la tabla con particiones mycolumntable
seleccionando datos de mytable2
(una tabla sin particiones).
INSERT INTO project_id.dataset.mycolumntable (ts, field1) SELECT ts, id FROM project_id.dataset.mytable2
Eliminar datos
Para eliminar filas de una tabla con particiones, se usa una declaración de DML DELETE
.
Eliminar datos de tablas con particiones por hora de ingestión
La siguiente instrucción DELETE
elimina todas las filas de la partición del 1 de junio del 2017 ("2017-06-01"
) de mytable
donde field1
es igual a 21
. Para hacer referencia a la partición, usa la pseudocolumna _PARTITIONTIME
.
DELETE project_id.dataset.mytable WHERE field1 = 21 AND _PARTITIONTIME = "2017-06-01"
Eliminar datos de tablas con particiones
Eliminar datos de una tabla con particiones mediante DML es lo mismo que eliminar datos de una tabla sin particiones.
Por ejemplo, la siguiente instrucción DELETE
elimina todas las filas de la partición del 1 de junio del 2017 ("2017-06-01"
) de mycolumntable
donde field1
es igual a 21
.
DELETE project_id.dataset.mycolumntable WHERE field1 = 21 AND DATE(ts) = "2017-06-01"
Usar la instrucción DELETE de DML para eliminar particiones
Si una instrucción DELETE
apta abarca todas las filas de una partición, BigQuery elimina toda la partición. Esta eliminación se realiza sin analizar bytes ni consumir ranuras. En el siguiente ejemplo de una instrucción DELETE
se cubre toda la partición de un filtro en la pseudocolumna _PARTITIONDATE
:
DELETE mydataset.mytable WHERE _PARTITIONDATE IN ('2076-10-07', '2076-03-06');
Descalificaciones habituales
Es posible que las consultas con las siguientes características no se beneficien de la optimización:
- Cobertura de partición parcial
- Referencias a columnas que no son de partición
- Datos ingeridos recientemente a través de la API Storage Write de BigQuery o de la API de streaming antigua
- Filtros con subconsultas o predicados no admitidos
La idoneidad para la optimización puede variar en función del tipo de partición, los metadatos de almacenamiento subyacentes y los predicados de filtro. Como práctica recomendada, haz una prueba de funcionamiento para verificar que la consulta da como resultado 0 bytes procesados.
Transacción con varias instrucciones
Esta optimización funciona en una transacción con varias instrucciones. En el siguiente ejemplo de consulta se sustituye una partición por datos de otra tabla en una sola transacción, sin analizar la partición para la instrucción DELETE
.
DECLARE REPLACE_DAY DATE; BEGIN TRANSACTION; -- find the partition which we want to replace SET REPLACE_DAY = (SELECT MAX(d) FROM mydataset.mytable_staging); -- delete the entire partition from mytable DELETE FROM mydataset.mytable WHERE part_col = REPLACE_DAY; -- insert the new data into the same partition in mytable INSERT INTO mydataset.mytable SELECT * FROM mydataset.mytable_staging WHERE part_col = REPLACE_DAY; COMMIT TRANSACTION;
Actualizar datos
Puedes usar una declaración UPDATE
para actualizar filas de una tabla con particiones.
Actualizar datos en tablas con particiones por hora de ingestión
La siguiente instrucción UPDATE
mueve filas de una partición a otra.
Las filas de la partición del 1 de mayo del 2017 (“2017-05-01”
) de mytable
en las que field1
es igual a 21
se mueven a la partición del 1 de junio del 2017 (“2017-06-01”
).
UPDATE project_id.dataset.mytable SET _PARTITIONTIME = "2017-06-01" WHERE _PARTITIONTIME = "2017-05-01" AND field1 = 21
Actualizar datos en tablas con particiones
Actualizar datos de una tabla con particiones mediante DML es lo mismo que actualizar datos de una tabla sin particiones. Por ejemplo, la siguiente instrucción UPDATE
mueve filas de una partición a otra. Las filas de la partición del 1 de mayo del 2017 (“2017-05-01”
) de mytable
en las que field1
es igual a 21
se mueven a la partición del 1 de junio del 2017 (“2017-06-01”
).
UPDATE project_id.dataset.mycolumntable SET ts = "2017-06-01" WHERE DATE(ts) = "2017-05-01" AND field1 = 21
DML en tablas con particiones por hora, mes y año
Puedes usar instrucciones DML para modificar una tabla con particiones por hora, mes o año. Indica el intervalo de horas, meses o años de las fechas, marcas de tiempo o fechas y horas pertinentes, como en el siguiente ejemplo de tablas con particiones mensuales:
bq query --nouse_legacy_sql 'DELETE FROM my_dataset.my_table WHERE TIMESTAMP_TRUNC(ts_column, MONTH) = "2020-01-01 00:00:00";'
Otro ejemplo de tablas con particiones por la columna DATETIME
:
bq query --nouse_legacy_sql 'DELETE FROM my_dataset.my_table WHERE dt_column BETWEEN DATETIME("2020-01-01") AND DATETIME("2020-05-01");'
Usar una instrucción MERGE
Puedes usar una declaración MERGE
de DML para combinar las operaciones INSERT
, UPDATE
y DELETE
de una tabla con particiones en una sola declaración y ejecutarlas de forma atómica.
Eliminar particiones al usar una instrucción MERGE
Cuando ejecutas una instrucción MERGE
en una tabla particionada, puedes limitar las particiones que se analizan incluyendo la columna de partición en un filtro de subconsulta, en un filtro search_condition
o en un filtro merge_condition
.
La poda puede producirse al analizar la tabla de origen, la de destino o ambas.
En cada uno de los ejemplos siguientes se consulta una tabla con particiones por hora de ingestión usando la pseudocolumna _PARTITIONTIME
como filtro.
Usar una subconsulta para filtrar datos de origen
En la siguiente instrucción MERGE
, la subconsulta de la cláusula USING
filtra la pseudocolumna _PARTITIONTIME
de la tabla de origen.
MERGE dataset.target T USING (SELECT * FROM dataset.source WHERE _PARTITIONTIME = '2018-01-01') S ON T.COLUMN_ID = S.COLUMN_ID WHEN MATCHED THEN DELETE
Si observamos el plan de ejecución de la consulta, la subconsulta se ejecuta primero. Solo se analizan las filas de la partición '2018-01-01'
de la tabla de origen. Esta es la fase correspondiente del plan de consulta:
READ $10:name, $11:_PARTITIONTIME
FROM temp.source
WHERE equal($11, 1514764800.000000000)
Usar un filtro en el search_condition
de un when_clause
Si un search_condition
contiene un filtro, el optimizador de consultas intenta eliminar particiones. Por ejemplo, en la siguiente instrucción MERGE
, cada cláusula WHEN
MATCHED
y WHEN NOT MATCHED
contiene un filtro en la pseudocolumna _PARTITIONTIME
.
MERGE dataset.target T USING dataset.source S ON T.COLUMN_ID = S.COLUMN_ID WHEN MATCHED AND T._PARTITIONTIME = '2018-01-01' THEN UPDATE SET COLUMN_ID = S.COLUMN_ID WHEN MATCHED AND T._PARTITIONTIME = '2018-01-02' THEN UPDATE SET COLUMN_ID = S.COLUMN_ID + 10 WHEN NOT MATCHED BY SOURCE AND T._PARTITIONTIME = '2018-01-03' THEN DELETE
Durante la fase de unión, solo se analizan las siguientes particiones de la tabla de destino: '2018-01-01'
, '2018-01-02'
y '2018-01-03'
, es decir, la unión de todos los filtros search_condition
.
En el plan de ejecución de la consulta:
READ
$1:COLUMN_ID, $2:_PARTITIONTIME, $3:$file_temp_id, $4:$row_temp_id
FROM temp.target
WHERE or(equal($2, 1514764800.000000000), equal($2, 1514851200.000000000), equal($2, 1514937600.000000000))
Sin embargo, en el siguiente ejemplo, la cláusula WHEN NOT MATCHED BY SOURCE
no tiene una expresión de filtro:
MERGE dataset.target T USING dataset.source S ON T.COLUMN_ID = S.COLUMN_ID WHEN MATCHED AND T._PARTITIONTIME = '2018-01-01' THEN UPDATE SET COLUMN_ID = S.COLUMN_ID WHEN NOT MATCHED BY SOURCE THEN UPDATE SET COLUMN_ID = COLUMN_ID + 1
Esta consulta debe analizar toda la tabla de destino para calcular la cláusula WHEN NOT MATCHED BY
SOURCE
. Por lo tanto, no se elimina ninguna partición.
Usar un predicado falso constante en un merge_condition
Si usa las cláusulas WHEN NOT MATCHED
y WHEN NOT MATCHED BY SOURCE
juntas, BigQuery suele realizar una unión externa completa, que no se puede podar. Sin embargo, si la condición de combinación usa un predicado constante falso, BigQuery puede usar la condición de filtro para eliminar particiones. Para obtener más información sobre el uso de predicados constantes falsos, consulta la descripción de la cláusula merge_condition
en la documentación de la instrucción MERGE
.
En el siguiente ejemplo, solo se analiza la partición '2018-01-01'
de las tablas de destino y de origen.
MERGE dataset.target T USING dataset.source S ON FALSE WHEN NOT MATCHED AND _PARTITIONTIME = '2018-01-01' THEN INSERT(COLUMN_ID) VALUES(COLUMN_ID) WHEN NOT MATCHED BY SOURCE AND _PARTITIONTIME = '2018-01-01' THEN DELETE
Usar un filtro en una merge_condition
El optimizador de consultas intenta usar un filtro en un merge_condition
para eliminar particiones. El optimizador de consultas puede o no insertar el predicado en la fase de análisis de la tabla, en función del tipo de combinación.
En el siguiente ejemplo, se usa merge_condition
como predicado para unir las tablas de origen y de destino. El optimizador de consultas puede insertar este predicado cuando analiza ambas tablas. Como resultado, la consulta solo analiza la '2018-01-01'
partición de las tablas de destino y de origen.
MERGE dataset.target T USING dataset.source S ON T.COLUMN_ID = S.COLUMN_ID AND T._PARTITIONTIME = '2018-01-01' AND S._PARTITIONTIME = '2018-01-01' WHEN MATCHED THEN UPDATE SET COLUMN_ID = NEW_VALUE
En el siguiente ejemplo, merge_condition
no contiene un predicado para la tabla de origen, por lo que no se puede realizar ninguna eliminación de particiones en la tabla de origen. La instrucción contiene un predicado para la tabla de destino, pero usa una cláusula WHEN NOT MATCHED BY SOURCE
en lugar de una cláusula WHEN MATCHED
. Esto significa que la consulta tiene que analizar toda la tabla de destino para buscar las filas que no coinciden.
MERGE dataset.target T USING dataset.source S ON T.COLUMN_ID = S.COLUMN_ID AND T._PARTITIONTIME = '2018-01-01' WHEN NOT MATCHED BY SOURCE THEN UPDATE SET COLUMN_ID = NEW_VALUE
Limitaciones
Para obtener información sobre las limitaciones de DML, consulta la sección Limitaciones de la página de referencia de DML.
Cuotas
Para obtener información sobre las cuotas de DML, consulta Declaraciones de DML en la página Cuotas y límites.
Precios
Para obtener información sobre los precios de DML, consulta Precios de DML para tablas con particiones.
Seguridad de las tablas
Para controlar el acceso a las tablas de BigQuery, consulta el artículo sobre cómo controlar el acceso a los recursos con la gestión de identidades y accesos.
Siguientes pasos
- Consulta cómo crear tablas con particiones.
- Consulta cómo consultar tablas con particiones.
- Consulta una introducción a DML.
- Consulta cómo redactar instrucciones DML con la sintaxis de DML.