En esta página se describen las prácticas recomendadas para usar el lenguaje de manipulación de datos (DML) y el DML particionado en bases de datos con dialecto de GoogleSQL y PostgreSQL.
Usa una cláusula WHERE
para reducir el ámbito de los bloqueos
Ejecutas instrucciones DML dentro de transacciones de lectura y escritura. Cuando Spanner lee datos, adquiere bloqueos de lectura compartidos en partes limitadas de los intervalos de filas que lees. En concreto, adquiere estos bloqueos solo en las columnas a las que accedes. Los bloqueos pueden incluir datos que no
cumplan la condición de filtro de la cláusula WHERE
.
Cuando Spanner modifica datos mediante instrucciones DML, adquiere bloqueos exclusivos en los datos específicos que estás modificando. Además, adquiere bloqueos compartidos de la misma forma que cuando lees datos. Si tu solicitud incluye intervalos de filas grandes o una tabla completa, los bloqueos compartidos pueden impedir que otras transacciones avancen en paralelo.
Para modificar los datos de la forma más eficiente posible, utilice una cláusula WHERE
que permita a Spanner leer solo las filas necesarias. Puedes conseguir este objetivo con un filtro en la clave principal o en la clave de un índice secundario. La cláusula WHERE
limita el ámbito de los bloqueos compartidos y permite que Spanner procese la actualización de forma 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ía ejecutar la siguiente instrucción DML, pero obliga a Spanner a analizar toda la tabla y adquiere bloqueos compartidos que cubren toda la tabla. Por lo tanto, 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, incluya la columna SingerId
en la cláusula WHERE
. La columna SingerId
es la única columna de clave principal 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 ningún índice en FirstName
o LastName
, debes analizar toda la tabla para encontrar los cantantes objetivo. Si no quieres añadir 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 principal de la tabla Singers
. Para encontrarlo, ejecuta SELECT
en una transacción de solo lectura independiente 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 instrucciones DML y mutaciones en la misma transacción
Spanner almacena en búfer las inserciones, las actualizaciones y las eliminaciones realizadas mediante instrucciones DML en el lado del servidor, y los resultados son visibles para las instrucciones SQL y DML posteriores dentro de la misma transacción. Este comportamiento es diferente de la API Mutation, 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. 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.
Evita usar instrucciones DML y mutaciones en la misma transacción. Si usas ambos en la misma transacción, debes tener en cuenta el orden de ejecución en el código de tu biblioteca de cliente. Si una transacción contiene tanto instrucciones DML como mutaciones en la misma solicitud, Spanner ejecuta las instrucciones DML antes que las mutaciones.
En el caso de las operaciones que solo se admiten mediante mutaciones, puede combinar instrucciones de DML y mutaciones en la misma transacción (por ejemplo, insert_or_update
).
Si usas ambos, el búfer solo escribe al final de la transacción.
Usar 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 instrucció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 instrucció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
DML con particiones usa una o varias transacciones que pueden ejecutarse y confirmarse en momentos diferentes. Si usas las funciones fecha o marca de tiempo, es posible que las filas modificadas contengan valores diferentes.
Mejorar la latencia con DML por lotes
Para reducir la latencia, usa DML por lotes para enviar varias declaraciones de DML a Spanner en un solo viaje de ida y vuelta entre el cliente y el servidor.
DML por lotes puede aplicar optimizaciones a grupos de instrucciones de un lote para permitir actualizaciones de datos más rápidas y eficientes.
Ejecutar escrituras con una sola solicitud
Spanner optimiza automáticamente los grupos contiguos de instrucciones por lotes similares de
INSERT
,UPDATE
oDELETE
que tienen diferentes valores de parámetros, si no infringen las dependencias de datos.Por ejemplo, supongamos que quiere insertar un gran conjunto de filas nuevas en una tabla llamada
Albums
. Para permitir que Spanner optimice todas las instruccionesINSERT
necesarias en una sola acción eficiente del lado del servidor, empieza escribiendo una instrucción DML adecuada que use parámetros de consulta SQL:INSERT INTO Albums (SingerId, AlbumId, AlbumTitle) VALUES (@Singer, @Album, @Title);
A continuación, envía a Spanner un lote de DML que invoque esta instrucción de forma repetida y contigua, con las repeticiones que solo difieran en los valores que asignes a los tres parámetros de consulta de la instrucción. Spanner optimiza estas instrucciones DML estructuralmente idénticas en una sola operación del lado del servidor antes de ejecutarla.
Ejecutar operaciones de escritura en paralelo
Spanner optimiza automáticamente los grupos contiguos de instrucciones DML ejecutándolos en paralelo cuando no se infringen las dependencias de datos. Esta optimización mejora el rendimiento de un conjunto más amplio de declaraciones de DML por lotes, ya que se puede aplicar a una combinación de tipos de declaraciones de DML (
INSERT
,UPDATE
yDELETE
) y a declaraciones de DML con o sin parámetros.Por ejemplo, nuestro esquema de muestra tiene las tablas
Singers
,Albums
yAccounts
.Albums
se entrelaza conSingers
y almacena información sobre los álbumes deSingers
. El siguiente grupo contiguo de instrucciones 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 instrucciones DML ejecutándolas en paralelo. Las escrituras se aplican en el orden de las instrucciones del lote y se mantiene la semántica de DML del lote si falla una instrucción durante la ejecución.