Compara DML y mutaciones

El lenguaje de manipulación de datos (DML) y las mutaciones son dos API en Cloud Spanner que puedes usar para modificar datos. Cada uno ofrece funciones de manipulación de datos similares. En esta página, se comparan ambos enfoques.

¿Qué es el lenguaje de manipulación de datos (DML)?

El lenguaje de manipulación de datos (DML) en Cloud Spanner te permite manipular datos en tus tablas de base de datos con declaraciones INSERT, UPDATE y DELETE. Puedes ejecutar declaraciones DML con las bibliotecas cliente, Cloud Console y gcloud spanner.

Cloud Spanner ofrece las dos implementaciones de la ejecución de DML, cada una con propiedades diferentes.

  • DML estándar: adecuado para cargas de trabajo estándar de procesamiento de transacciones en línea (OLTP)

    Para obtener más información, incluidas muestras de código, consulta Usa DML.

  • DML particionado: está diseñado para actualizaciones y eliminaciones masivas, como en los siguientes ejemplos.

    • Recolección de elementos no usados y limpieza periódicos. Por ejemplo, la eliminación de filas antiguas o la configuración de columnas como NULL.

    • El restablecimiento de columnas nuevas con valores predeterminados. Un ejemplo es el uso de una declaración UPDATE para configurar el valor de una columna nueva como False en el que se encuentra actualmente NULL.

    Para obtener más información, incluidas muestras de código, consulta Usa DML particionado.

¿Qué son las mutaciones?

Una mutación representa una secuencia de inserciones, actualizaciones y eliminaciones que aplica atómicamente Cloud Spanner a diferentes filas y tablas de una base de datos. Puedes incluir operaciones que se apliquen a diferentes filas o a distintas tablas, en una mutación. Después de definir una o más mutaciones que contienen una o más operaciones de escritura, debes aplicar la mutación para confirmar las escrituras. Cada cambio se aplica en el orden en que se agregaron a la mutación.

Para obtener más información, incluidas muestras de código, consulta Inserta, actualiza y borra datos mediante mutaciones.

Comparación de características entre DML y mutaciones

En la tabla siguiente, se resume la compatibilidad de DML y mutación de la base de datos y las funciones comunes de la base de datos.

Operaciones DML Mutaciones
Inserta datos Admitido Admitido
Borrar datos Admitido Admitido
Actualizar datos Admitido Admitido
Lee tus escrituras (RYW) Admitido No compatible
Parte superior (insertar o actualizar) No compatible Admitido
Sintaxis de SQL Admitido No compatible
Comprobación de restricciones Después de cada declaración A la hora de confirmación

DML y mutaciones diferen en su compatibilidad con las siguientes funciones.

  • Semántica de Lee tus escrituras: Se leen tus escrituras para leer los resultados no confirmados en una transacción activa. Los cambios que realices mediante las declaraciones DML serán visibles para las declaraciones posteriores de la misma transacción. No es lo mismo que usar mutaciones, cuando los cambios no son visibles en ninguna lectura (incluidas las lecturas realizadas en la misma transacción) hasta que la transacción se confirma. Esto se debe a que las mutaciones en una transacción se almacenan en búfer de forma local (del cliente) y se envían al servidor como parte de la operación de confirmación. Como resultado, las mutaciones de la solicitud de confirmación no son visibles para las instrucciones de SQL o declaraciones de DML dentro de la misma transacción.

  • Upser: DML no admite una actualización nativa, una operación que inserta filas en una tabla de base de datos si aún no existen, o las actualiza si lo tienen. Sin embargo, existe una operación insert_or_update en el mundo de las mutaciones. Las aplicaciones que usan DML pueden evitar esta limitación si leen la fila primero y, luego, usan la declaración DML adecuada.

  • Verificación de restricciones: Cloud Spanner verifica las restricciones después de que se realice cada declaración DML. No es lo mismo que usar mutaciones, para las que Cloud Spanner almacena las mutaciones en el cliente hasta la confirmación y verifica las restricciones en el momento de la confirmación. La evaluación de restricciones después de cada declaración DML permite que Cloud Spanner garantice que los datos que muestra una consulta posterior en la misma transacción muestren los datos que son coherentes con el esquema.

  • Sintaxis de SQL: DML proporciona una forma convencional de manipular los datos. Puedes volver a usar las habilidades de SQL para modificar los datos mediante la API de DML.

Práctica recomendada: Evita combinar DML y mutación en la misma transacción

Si una transacción contiene mutaciones y declaraciones DML en la solicitud de confirmación, Cloud Spanner ejecuta las declaraciones DML antes de las mutaciones. Para evitar tener que dar cuenta del orden de ejecución en el código de tu biblioteca cliente, debes usar las declaraciones DML o las mutaciones en una sola transacción, pero no en ambas.

El siguiente ejemplo de Java ilustra un comportamiento potencialmente sorprendente. El código inserta dos filas en Albumslbumes con la API de mutación. El fragmento y luego llama a executeUpdate() para actualizar las filas recién insertadas y llama a executeQuery() para leer los álbumes actualizados.

static void updateMarketingBudget(DatabaseClient dbClient) {
  dbClient
      .readWriteTransaction()
      .run(
          new TransactionCallable<Void>() {
            @Override
            public Void run(TransactionContext transaction) throws Exception {
               transaction.buffer(
                    Mutation.newInsertBuilder("Albums")
                        .set("SingerId")
                        .to(1)
                        .set("AlbumId")
                        .to(1)
                        .set("AlbumTitle")
                        .to("Total Junk")
                        .set("MarketingBudget")
                        .to(800)
                        .build());
               transaction.buffer(
                    Mutation.newInsertBuilder("Albums")
                        .set("SingerId")
                        .to(1)
                        .set("AlbumId")
                        .to(2)
                        .set("AlbumTitle")
                        .to("Go Go Go")
                        .set("MarketingBudget")
                        .to(200)
                        .build());

                // This UPDATE will not include the Albums inserted above.
                String sql =
                  "UPDATE Albums SET MarketingBudget = MarketingBudget * 2"
                      + " WHERE SingerId = 1";
                long rowCount = transaction.executeUpdate(Statement.of(sql));
                System.out.printf("%d records updated.\n", rowCount);

                // Read a newly updated record.
                sql =
                  "SELECT SingerId, AlbumId, AlbumTitle FROM Albums"
                      + " WHERE SingerId = 1 AND MarketingBudget < 1000";
                ResultSet resultSet =
                                 transaction.executeQuery(Statement.of(sql));
                while (resultSet.next()) {
                   System.out.printf(
                        "%s %s\n",
                        resultSet.getString("FirstName"),
                        resultSet.getString("LastName"));
                }
                return null;
              }
            });
}

Si ejecutara este código, verá 0 registros actualizados. ¿Por qué? Esto sucede porque los cambios que usamos con las mutaciones no son visibles para las instrucciones posteriores hasta que la transacción se confirma. Lo ideal es que haya escrituras en búfer solo al final de la transacción.

Próximos pasos