Comparar DMLs y mutaciones

El lenguaje de manipulación de datos (DML) y las mutaciones son dos APIs de Spanner que puedes usar para modificar datos. Cada una de ellas ofrece funciones similares de manipulación de datos. 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) de Spanner te permite manipular datos en las tablas de tu base de datos mediante las instrucciones INSERT, UPDATE y DELETE. Puedes ejecutar instrucciones DML mediante las bibliotecas de cliente, la Google Cloud consola y gcloud spanner.

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

  • DML estándar: adecuado para cargas de trabajo de procesamiento de transacciones online (OLTP) estándar.

    Para obtener más información, incluidos ejemplos de código, consulta Usar DML.

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

    • Limpieza periódica y recolección de elementos no utilizados. Por ejemplo, eliminar filas antiguas o asignar el valor NULL a las columnas.

    • Rellenar las nuevas columnas con valores predeterminados. Por ejemplo, puede usar una instrucción UPDATE para asignar el valor False a una columna nueva cuando sea NULL.

    Para obtener más información, incluidos ejemplos de código, consulta Usar DML con particiones.

    Puedes usar escrituras por lotes para un gran número de operaciones de escritura sin operaciones de lectura que no requieran transacciones atómicas. Para obtener más información, consulta Modificar datos mediante escrituras por lotes.

¿Qué son las mutaciones?

Una mutación representa una secuencia de inserciones, actualizaciones y eliminaciones que Spanner aplica de forma atómica a diferentes filas y tablas de una base de datos. Puedes incluir operaciones que se apliquen a diferentes filas o tablas en una mutación. Después de definir una o varias mutaciones que contengan una o varias escrituras, debes aplicar la mutación para confirmar las escrituras. Cada cambio se aplica en el orden en el que se han añadido a la mutación.

Para obtener más información, incluidos ejemplos de código, consulta Insertar, actualizar y eliminar datos mediante mutaciones.

Comparación de funciones entre DML y mutaciones

En la siguiente tabla se resumen las operaciones y funciones de bases de datos comunes compatibles con DML y mutaciones.

Operaciones DML Mutaciones
Insertar datos Compatible Compatible
Eliminar datos Compatible Compatible
Actualizar datos Compatible Compatible
Insertar o ignorar datos Compatible No admitido
Read Your Writes (RYW) Compatible No admitido
Insertar o actualizar datos (upsert) Compatible Compatible
Sintaxis de SQL Compatible No admitido
Comprobación de restricciones Después de cada afirmación En el momento de la confirmación

DML y las mutaciones difieren en su compatibilidad con las siguientes funciones:

  • Lectura de tus escrituras: lectura de resultados no confirmados en una transacción activa. Los cambios que hagas con instrucciones DML serán visibles para las instrucciones posteriores de la misma transacción. Esto es diferente de usar mutaciones, donde los cambios no se ven en ninguna lectura (incluidas las lecturas realizadas en la misma transacción) hasta que se confirma la transacción. Esto se debe a que las mutaciones de una transacción se almacenan en el búfer del lado del cliente (localmente) y se envían al servidor como parte de la operación de confirmación. Por lo tanto, las mutaciones de la solicitud de confirmación no son visibles para las instrucciones SQL o DML de la misma transacción.

  • Comprobación de restricciones: Spanner comprueba las restricciones después de cada instrucción DML. Esto es diferente de usar mutaciones, donde Spanner almacena en búfer las mutaciones en el cliente hasta que se confirman y comprueba las restricciones en el momento de la confirmación. Al evaluar las restricciones después de cada instrucción DML, Spanner puede garantizar que los datos devueltos por una consulta posterior en la misma transacción sean coherentes con el esquema.

  • Sintaxis de SQL: DML proporciona una forma convencional de manipular datos. Puedes reutilizar tus conocimientos de SQL para modificar los datos mediante la API DML.

Práctica recomendada: no mezclar DML y mutaciones en la misma transacción

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

En el siguiente ejemplo de Java se muestra un comportamiento que puede resultar sorprendente. El código inserta dos filas en Albums mediante la API Mutation. A continuación, el fragmento llama a executeUpdate() para actualizar las filas insertadas y 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 ejecutaras este código, verías el mensaje 0 registros actualizados. ¿Por qué? Esto ocurre porque los cambios que hemos hecho con Mutations no son visibles para las instrucciones posteriores hasta que se confirma la transacción. Lo ideal sería que solo tuviéramos escrituras almacenadas en búfer al final de la transacción.

Siguientes pasos