En esta página se proporcionan directrices para cargar de forma masiva grandes cantidades de datos en Spanner de forma eficiente.
Tienes varias opciones para cargar datos de forma masiva en Spanner:
- Insertar filas con el lenguaje de manipulación de datos (DML).
- Insertar filas con mutaciones.
- Importar datos con el conector de Dataflow.
- Importar una base de datos mediante archivos Avro.
- Importa datos en formato CSV.
Aunque también puedes insertar filas con la CLI de Google Cloud, no te recomendamos que la uses para la carga masiva.
Directrices de rendimiento para la carga en bloque
Para conseguir un rendimiento óptimo de la carga masiva, aprovecha al máximo la partición para distribuir la escritura de los datos entre las tareas de los trabajadores.
Spanner usa la división basada en la carga para distribuir de forma uniforme la carga de datos entre los recursos de computación de la instancia. Después de unos minutos con una carga elevada, Spanner introduce límites de división entre las filas. Por lo general, si la carga de datos está bien distribuida y sigues las prácticas recomendadas para el diseño de esquemas y la carga masiva, el rendimiento de escritura debería duplicarse cada pocos minutos hasta que se saturen los recursos de CPU disponibles en tu instancia.
Particionar los datos por clave principal
Spanner particiona automáticamente las tablas en intervalos más pequeños. La clave principal de una fila determina dónde se particiona.
Para obtener un rendimiento de escritura óptimo en las cargas masivas, particione los datos por clave principal con este patrón:
- Cada partición contiene un intervalo de filas consecutivas, determinado por las columnas de clave.
- Cada confirmación contiene datos de una sola partición.
Recomendamos que el número de particiones sea 10 veces el número de nodos de tu instancia de Spanner. Para asignar filas a particiones, sigue estos pasos:
- Ordena los datos por clave principal.
- Divide los datos en 10 * (número de nodos) particiones independientes de igual tamaño.
- Crea y asigna una tarea de trabajador independiente a cada partición. Las tareas de trabajador se crean en tu aplicación. No es una función de Spanner.
Siguiendo este patrón, deberías ver un rendimiento máximo de escritura masiva general de entre 10 y 20 MB por segundo y nodo en el caso de cargas grandes.
A medida que carga datos, Spanner crea y actualiza divisiones para equilibrar la carga de los nodos de su instancia. Durante este proceso, es posible que experimentes reducciones temporales del rendimiento.
Ejemplo
Tienes una configuración regional con 3 nodos. Tienes 90.000 filas en una tabla no intercalada. Las claves principales de la tabla van del 1 al 90.000.
- Filas: 90.000 filas
- Nodos: 3
- Particiones: 10 * 3 = 30
- Filas por partición: 90.000 / 30 = 3000.
La primera partición incluye el intervalo de claves del 1 al 3000. La segunda partición incluye el intervalo de claves del 3001 al 6000. La partición 30 incluye el intervalo de claves 87001 a 90000. No deberías usar claves secuenciales en una tabla grande. Este ejemplo es solo una demostración.
Cada tarea de trabajador envía las escrituras de una sola partición. En cada partición, debes escribir las filas de forma secuencial por clave principal. Escribir filas de forma aleatoria con respecto a la clave principal también debería proporcionar un rendimiento razonablemente alto. Medir las pruebas te permitirá saber qué enfoque ofrece el mejor rendimiento para tu conjunto de datos.
Carga en bloque sin particiones
Escribir un conjunto contiguo de filas en una confirmación puede ser más rápido que escribir filas aleatorias. Es probable que las filas aleatorias también incluyan datos de diferentes particiones.
Cuando se escriben más particiones en una confirmación, se necesita más coordinación entre los servidores, lo que aumenta la latencia y la sobrecarga de la confirmación.
Es probable que haya varias particiones implicadas, ya que cada fila aleatoria podría pertenecer a una partición diferente. En el peor de los casos, cada escritura implica todas las particiones de tu instancia de Spanner. Como se ha mencionado anteriormente, el rendimiento de escritura se reduce cuando hay más particiones implicadas.
Evitar la sobrecarga
Es posible enviar más solicitudes de escritura de las que puede gestionar Spanner. Spanner gestiona la sobrecarga anulando las transacciones, lo que se denomina rechazo. En el caso de las transacciones de solo escritura, Spanner vuelve a intentar la transacción automáticamente. En esos casos, el rechazo se muestra como una latencia alta. En situaciones de mucha carga, el retroceso puede durar hasta un minuto. Durante cargas muy pesadas, el rechazo puede durar varios minutos. Para evitar que se rechacen, debes limitar las solicitudes de escritura para mantener el uso de la CPU dentro de unos límites razonables. También pueden aumentar el número de nodos para que el uso de la CPU se mantenga dentro de los límites.
Confirmar entre 1 y 5 MB de mutaciones a la vez
Cada escritura en Spanner conlleva una sobrecarga, tanto si la escritura es grande como si es pequeña. Para maximizar el rendimiento, maximiza la cantidad de datos almacenados por escritura. Las escrituras de mayor tamaño reducen la proporción de sobrecarga por escritura. Una buena técnica es que cada confirmación modifique cientos de filas. Cuando se escriben filas relativamente grandes, un tamaño de confirmación de entre 1 y 5 MB suele ofrecer el mejor rendimiento. Cuando se escriben valores pequeños o valores indexados, suele ser mejor escribir como máximo unos cientos de filas en una sola confirmación. Independientemente del tamaño de la confirmación y del número de filas, ten en cuenta que hay un límite de 80.000 mutaciones por confirmación. Para determinar el rendimiento óptimo, debes probar y medir el rendimiento.
Las confirmaciones de cambios de más de 5 MB o de más de unos cientos de filas no aportan ninguna ventaja adicional y pueden superar los límites de Spanner en cuanto al tamaño de las confirmaciones de cambios y las mutaciones por confirmación de cambios.
Directrices para los índices secundarios
Si tu base de datos tiene índices secundarios, debes elegir si quieres añadir los índices al esquema de la base de datos antes o después de cargar los datos de la tabla.
Si añades el índice antes de que se carguen los datos, el cambio de esquema se completará inmediatamente. Sin embargo, cada escritura que afecte al índice tardará más, ya que también tendrá que actualizar el índice. Cuando se completa la carga de datos, la base de datos se puede usar inmediatamente con todos los índices. Para crear una tabla y sus índices al mismo tiempo, envía las instrucciones DDL de la tabla y los índices nuevos en una sola solicitud a Spanner.
Si añades el índice después de cargar los datos, cada escritura será eficiente. Sin embargo, el cambio de esquema de cada relleno de índice puede tardar mucho tiempo. La base de datos no se puede usar por completo y las consultas no pueden usar los índices hasta que se completen todos los cambios del esquema. La base de datos puede seguir atendiendo escrituras y consultas, pero a un ritmo más lento.
Te recomendamos que añadas los índices que sean fundamentales para tu aplicación empresarial antes de cargar los datos. En el caso de los índices no críticos, añádelos después de migrar los datos.
Usar INTERLEAVE IN
durante la carga en bloque
En los esquemas con muchas referencias de elementos principales y secundarios en las tablas, siempre debe cargar el elemento principal antes que los secundarios para garantizar la integridad referencial. Esta orquestación puede ser complicada, sobre todo si hay varios niveles de jerarquía. Esta complejidad también dificulta mucho la creación de lotes y la paralelización, y puede influir considerablemente en el tiempo total de carga masiva. En Spanner, estas relaciones se aplican mediante INTERLEAVE IN PARENT
o claves externas. Para obtener más información, consulta la documentación de CREATE TABLE
.
Si añades una clave externa después de una carga masiva, se crea un índice de forma interna, por lo que debes seguir las directrices que se indican en secondary-indexes.
Sin embargo, en el caso de las tablas INTERLEAVE IN PARENT
, se recomienda que crees todas las tablas con semántica INTERLEAVE IN
durante la carga masiva, que entrelaza físicamente las filas, pero no aplica la integridad referencial. De esta forma, se aprovechan las ventajas de rendimiento de la localidad, pero no es necesario hacer el pedido por adelantado. Ahora que se pueden insertar filas secundarias antes de la fila principal correspondiente, Spanner puede escribir en todas las tablas en paralelo.
Una vez que se hayan cargado todas las tablas, puede migrar las tablas intercaladas para empezar a
aplicar la relación superior-secundaria con la instrucción
ALTER TABLE t1 SET INTERLEAVE IN PARENT t2
. Valida la integridad referencial y falla si hay filas secundarias huérfanas. Si la validación falla, identifica las filas principales que faltan con la siguiente consulta.
SELECT pk1, pk2 FROM child
EXCEPT DISTINCT
SELECT pk1, pk2 FROM parent;
Probar y medir el rendimiento
Predecir el rendimiento puede ser difícil. Te recomendamos que pruebes tu estrategia de carga masiva antes de ejecutar la carga final. Para ver un ejemplo detallado sobre cómo usar la partición y monitorizar el rendimiento, consulta Maximizar el rendimiento de la carga de datos.
Prácticas recomendadas para la carga periódica en bloque en una base de datos
Si vas a actualizar una base de datos que contiene datos, pero no tiene ningún índice secundario, las recomendaciones de este documento siguen siendo válidas.
Si tienes índices secundarios, las instrucciones pueden dar resultados razonables. El rendimiento depende de cuántas divisiones, de media, se incluyan en tus transacciones. Si el rendimiento baja demasiado, puedes probar lo siguiente:
- Incluye un número menor de mutaciones en cada confirmación, lo que podría aumentar el rendimiento.
- Si el tamaño de la subida es mayor que el tamaño total actual de la tabla que se va a actualizar, elimina los índices secundarios y vuelve a añadirlos después de subir los datos. Este paso no suele ser necesario, pero puede mejorar el rendimiento.