Prácticas recomendadas para el lenguaje de manipulación de datos

En esta página, se describen las prácticas recomendadas para usar el lenguaje de manipulación de datos (DML) y el DML particionado.

Usa una cláusula WHERE para reducir el alcance de los bloqueos

Las declaraciones DML se pueden ejecutar dentro de transacciones de lectura y escritura. Cuando Spanner lee datos, adquiere bloqueos de lectura compartidos en partes limitadas de los rangos de filas que lees. En particular, adquiere estos bloqueos solo en las columnas a las que accedes. Los bloqueos pueden incluir datos que no cumplan con la condición del filtro de la cláusula WHERE.

Cuando Spanner modifica los datos con declaraciones DML, adquiere bloqueos exclusivos en los datos específicos que estás modificando. Además, adquiere bloqueos compartidos de la misma manera que cuando lees datos. Si tu solicitud incluye grandes rangos de filas o una tabla completa, es posible que los bloqueos compartidos impidan que otras transacciones progresen en paralelo.

Para modificar los datos de la manera más eficiente posible, usa una cláusula WHERE que permita que Spanner lea solo las filas necesarias. Puedes lograr este objetivo con un filtro en la clave primaria o en la clave de un índice secundario. La cláusula WHERE limita el alcance de los bloqueos compartidos y permite que Spanner procese la actualización de manera más eficiente.

Por ejemplo, supongamos que uno de los músicos de la tabla Singers cambia su nombre y tienes que actualizarlo en tu base de datos. Podrías ejecutar la siguiente declaración DML, pero obliga a Spanner a analizar toda la tabla y adquirir bloqueos compartidos que cubren toda la tabla. Como resultado, Spanner debe leer más datos de los necesarios, y las transacciones simultáneas no pueden modificar los datos en paralelo:

-- ANTI-PATTERN: SENDING AN UPDATE WITHOUT THE PRIMARY KEY COLUMN
-- IN THE WHERE CLAUSE

UPDATE Singers SET FirstName = "Marcel"
WHERE FirstName = "Marc" AND LastName = "Richards";

Para que la actualización sea más eficiente, incluye la columna SingerId en la cláusula WHERE. La columna SingerId es la única columna de clave primaria de la tabla Singers:

-- ANTI-PATTERN: SENDING AN UPDATE THAT MUST SCAN THE ENTIRE TABLE

UPDATE Singers SET FirstName = "Marcel"
WHERE FirstName = "Marc" AND LastName = "Richards"

Si no hay un índice en FirstName o LastName, debes analizar toda la tabla para encontrar los cantantes objetivo. Si no deseas agregar un índice secundario para que la actualización sea más eficiente, incluye la columna SingerId en la cláusula WHERE.

La columna SingerId es la única columna de clave primaria de la tabla Singers. Para encontrarlo, ejecuta SELECT en una transacción independiente de solo lectura antes de la transacción de actualización:


  SELECT SingerId
  FROM Singers
  WHERE FirstName = "Marc" AND LastName = "Richards"

  -- Recommended: Including a seekable filter in the where clause

  UPDATE Singers SET FirstName = "Marcel"
  WHERE SingerId = 1;

Evita usar mutaciones y declaraciones DML en la misma transacción

Spanner almacena en búfer las inserciones, actualizaciones y eliminaciones realizadas mediante declaraciones DML del lado del servidor, y los resultados son visibles para las declaraciones DML y las declaraciones DML posteriores dentro de la misma transacción. Este comportamiento es diferente de la API de mutación, en la que Spanner almacena en búfer las mutaciones del lado del cliente y las envía del lado del 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.

Evita usar tanto declaraciones DML como mutaciones en la misma transacción. Si usas ambos en la misma transacción, debes justificar el orden de ejecución en el código de la biblioteca cliente. Si una transacción contiene mutaciones y declaraciones DML en la misma solicitud, Spanner ejecuta las declaraciones DML antes de las mutaciones.

Para las operaciones que solo se admiten mediante mutaciones, es posible que desees combinar mutaciones y declaraciones DML en la misma transacción, por ejemplo, insert_or_update.

Si usas ambos, el búfer escribe solo al final de la transacción.

Usa la función PENDING_COMMIT_TIMESTAMP para escribir marcas de tiempo de confirmación

GoogleSQL

Usa la función PENDING_COMMIT_TIMESTAMP para escribir la marca de tiempo de confirmación en una declaración DML. Spanner selecciona la marca de tiempo de confirmación cuando se confirma la transacción.

PostgreSQL

Usa la función SPANNER.PENDING_COMMIT_TIMESTAMP() para escribir la marca de tiempo de confirmación en una declaración DML. Spanner selecciona la marca de tiempo de confirmación cuando se confirma la transacción.

DML particionado y funciones de fecha y marca de tiempo

El DML particionado usa una o más transacciones que pueden ejecutarse y confirmarse en momentos diferentes. Si usas las funciones de fecha o marca de tiempo, las filas modificadas pueden contener valores diferentes.

Mejora la latencia con DML por lotes

Para reducir la latencia, usa el DML por lotes a fin de enviar varias declaraciones DML a Spanner dentro de un único recorrido de ida y vuelta entre cliente y servidor.

El DML por lotes puede aplicar optimizaciones a grupos de declaraciones dentro de un lote para permitir actualizaciones de datos más rápidas y eficientes.

  • Ejecuta escrituras con una sola solicitud

    Spanner optimiza de forma automática los grupos contiguos de instrucciones en lotes INSERT, UPDATE o DELETE similares que tienen valores de parámetros diferentes si no infringen las dependencias de datos.

    Por ejemplo, imagina una situación en la que deseas insertar un gran conjunto de filas nuevas en una tabla llamada Albums. Para permitir que Spanner optimice todas las declaraciones INSERT requeridas en una sola acción eficiente del servidor, comienza por escribir una declaración DML adecuada que use parámetros de consulta en SQL:

    INSERT INTO Albums (SingerId, AlbumId, AlbumTitle) VALUES (@Singer, @Album, @Title);
    

    Luego, envía a Spanner un lote DML que invoque esta declaración de forma reiterada y contigua, y las repeticiones solo diferirán en los valores que vinculas a los tres parámetros de consulta de la declaración. Spanner optimiza estas declaraciones DML de estructura idéntica en una sola operación del servidor antes de ejecutarlas.

  • Ejecuta operaciones de escritura en paralelo

    Spanner optimiza de forma automática los grupos contiguos de declaraciones DML mediante la ejecución en paralelo cuando no infringe las dependencias de datos. Esta optimización aporta beneficios de rendimiento a un conjunto más amplio de declaraciones DML por lotes porque se pueden aplicar a una combinación de tipos de declaración DML (INSERT, UPDATE y DELETE) y a declaraciones DML parametrizadas o no parametrizadas.

    Por ejemplo, nuestro esquema de muestra tiene las tablas Singers, Albums y Accounts. Albums se intercala en Singers y almacena información sobre los álbumes de Singers. El siguiente grupo contiguo de declaraciones escribe filas nuevas en varias tablas y no tiene dependencias de datos complejas.

    INSERT INTO Singers (SingerId, Name) VALUES(1, "John Doe");
    INSERT INTO Singers (SingerId, Name) VALUES(2, "Marcel Richards");
    INSERT INTO Albums(SingerId, AlbumId, AlbumTitle) VALUES (1, 10001, "Album 1");
    INSERT INTO Albums(SingerId, AlbumId, AlbumTitle) VALUES (1, 10002, "Album 2");
    INSERT INTO Albums(SingerId, AlbumId, AlbumTitle) VALUES (2, 10001, "Album 1");
    UPDATE Accounts SET Balance = 100 WHERE AccountId = @AccountId;
    

    Spanner optimiza este grupo de declaraciones DML mediante la ejecución de las declaraciones en paralelo. Las escrituras se aplican en orden de las declaraciones en el lote y mantienen la semántica del DML por lotes si una declaración falla durante la ejecución.