Cette page fournit des instructions pour réaliser efficacement le chargement groupé de grandes quantités de données dans Spanner.
Plusieurs options s'offrent à vous pour charger des données de manière groupée dans Spanner :
- Insérer des lignes à l'aide du langage de manipulation de données (LMD)
- Insérer des lignes à l'aide de mutations
- Importez des données à l'aide du connecteur Dataflow.
- Importez une base de données à l'aide de fichiers Avro.
- Importer des données au format CSV
Bien que vous puissiez également insérer des lignes à l'aide de la Google Cloud CLI, nous vous déconseillons d'utiliser la CLI gcloud pour le chargement groupé.
Consignes relatives aux performances pour le chargement groupé
Optimisez votre utilisation du partitionnement pour optimiser les performances de chargement groupé pour répartir l'écriture des données entre les tâches de nœud de calcul.
Spanner utilise la répartition basée sur la charge pour répartir uniformément vos de données sur les ressources de calcul de l'instance. Après quelques minutes de charge élevée, Spanner lance les limites de division entre les lignes. En règle générale, si votre charge de données est bien distribuée et que vous suivez les bonnes pratiques relatives à la conception de schémas et au chargement groupé, votre débit en écriture devrait doubler toutes les quelques minutes jusqu'à ce que les ressources de processeur de l'instance soient saturées.
Partitionner les données par clé primaire
Spanner partitionne automatiquement les tables en plages plus petites. La clé primaire d'une ligne détermine où elle est partitionnée.
Pour obtenir un débit en écriture optimal pour les chargements groupés, partitionnez vos données par clé primaire selon ce modèle :
- Chaque partition contient une plage de lignes consécutives, déterminée par les colonnes de clé.
- Chaque commit contient des données pour une seule partition.
Nous vous recommandons d'utiliser un nombre de partitions 10 fois supérieur au nombre de nœuds de votre instance Spanner. Pour affecter des lignes aux partitions, procédez comme suit :
- Triez vos données par clé primaire.
- Divisez les données en 10 * (nombre de nœuds) partitions distinctes de taille égale.
- Créez et affectez une tâche de nœud de calcul distincte à chaque partition. La création des tâches de nœud de calcul s'effectue dans votre application. Il ne s'agit pas d'une clé Spanner .
En suivant ce schéma, vous devriez constater un débit en écriture groupé global atteignant jusqu'à 10 à 20 Mo par seconde par nœud pour les charges importantes.
À mesure que vous chargez des données, Spanner crée et met à jour des divisions pour équilibrer la charge exercée sur les nœuds de votre instance. Pendant ce processus, des baisses temporaires du débit peuvent survenir.
Exemple
Vous avez une configuration régionale avec trois nœuds. Vous disposez d'une table non entrelacée contenant 90 000 lignes. Les clés primaires de la table vont de 1 à 90 000.
- Lignes : 90 000
- Nœuds : 3
- Partitions : 10 * 3 = 30
- Lignes par partition : 90 000 / 30 = 3 000.
La première partition comprend la plage de clés 1 à 3 000. La deuxième partition comprend la plage de clés 3 001 à 6 000. La 30e partition comprend la plage de clés 87 001 à 90 000. (Il est déconseillé d'utiliser des clés séquentielles dans une grande table. Cet exemple n'est présenté qu'à des fins de démonstration.)
Chaque tâche de nœud de calcul envoie les écritures pour une partition. Dans chaque partition, vous devez écrire les lignes de manière séquentielle par clé primaire. L'écriture aléatoire de lignes en fonction de la clé primaire devrait également fournir un débit raisonnablement élevé. Vous pouvez exécuter des tests pour déterminer l'approche offrant les meilleures performances pour votre ensemble de données.
Si vous décidez de ne pas utiliser de partitions
L'écriture de lignes aléatoires dans un commit peut être plus lente que l'écriture d'un ensemble contigu de lignes dans un commit et toucher probablement des données dans différentes partitions. La latence du commit et les frais généraux sont plus élevés lorsque davantage de divisions sont en cours. écrit dans un commit, en raison d'une meilleure coordination entre les serveurs. Plusieurs divisions sont probablement impliquées, car chaque ligne aléatoire peut appartenir à une division différente. Dans le pire des cas chaque écriture implique toutes les divisions de votre Compute Engine. Comme indiqué précédemment, le débit en écriture est réduit lorsque davantage de divisions sont impliquées.
Chargement groupé sans partitionnement
Écrire un ensemble de lignes contigus dans un commit peut être plus rapide que l'écriture aléatoire lignes. Les lignes aléatoires incluent également probablement des données provenant de différentes partitions.
Lorsque davantage de partitions sont écrites dans un commit, une coordination plus importante entre les serveurs est requise, ce qui augmente la latence et les frais généraux du commit.
Plusieurs partitions sont probablement impliquées car chaque ligne aléatoire pourrait appartenir vers une autre partition. Dans le pire des cas, chaque écriture implique chaque partition de votre instance Spanner. Comme indiqué précédemment auparavant, le débit en écriture est réduit lorsque davantage de partitions sont impliquées.
Éviter la surcharge
Il est possible d'envoyer plus de requêtes d'écriture que Spanner ne peut identifiant. Spanner gère la surcharge en annulant les transactions. ce qui s’appelle un refus. Pour les transactions en écriture seule, Spanner une nouvelle tentative d'exécution de la transaction. Dans ce cas, le refus prend la forme une latence élevée. En cas de charges importantes, le refus peut durer jusqu'à une minute. Pendant des charges très lourdes, le refus peut durer plusieurs minutes. Pour éviter les refus de transaction, il est conseillé de limiter les requêtes d'écriture afin de maintenir l'utilisation du processeur dans des limites raisonnables. Les utilisateurs peuvent aussi augmenter le nombre de nœuds pour que l'utilisation du processeur ne dépasse pas les limites.
Commit entre 1 et 5 Mo de mutations à la fois
Chaque écriture dans Spanner entraîne une surcharge, que le volume de données à écrire soit volumineux ou non. Pour optimiser le débit, maximisez la quantité de données stockées par l'écriture. Les écritures de grande taille réduisent le ratio de surcharge par écriture. Un bonne technique pour ce faire serait que chaque commit mute des centaines de lignes. Lors de l'écriture de lignes relativement grandes, une taille de commit comprise entre 1 et 5 Mo offre généralement des performances optimales. Lors de l'écriture de petites valeurs ou de valeurs indexées, il est généralement préférable d'écrire au plus quelques centaines de lignes dans un même commit. Indépendamment de la taille de commit et du nombre de lignes, sachez qu'il existe une limite de 80 000 mutations par commit. Pour déterminer les performances optimales, vous devez tester et mesurer le débit.
Les commits de plus de 5 Mo ou ceux de quelques centaines de lignes ne présentent des avantages supplémentaires, au risque de dépasser le seuil limits sur la taille du commit et le nombre de mutations par commit.
Consignes relatives aux index secondaires
Si votre base de données contient des index secondaires, vous devez choisir d'ajouter les index au schéma de base de données avant ou après le chargement des données de la table.
L'ajout de l'index avant le chargement des données permet de terminer immédiatement la modification du schéma. Cependant, chaque écriture affectant l'index prend plus de temps, car il doit également mettre à jour l'index. Une fois le chargement des données terminé, la base de données est immédiatement utilisable avec tous les index en place. Pour créer une table et ses index en même temps, envoient les instructions LDD de la nouvelle table, de nouveaux index en une seule requête adressée à Spanner.
L'ajout de l'index après le chargement des données signifie que chaque écriture est efficace. Cependant, la modification du schéma de chaque remplissage de l'index peut prendre beaucoup de temps. La base de données n'est pas entièrement utilisable et les requêtes ne peuvent pas utiliser les index tant que que toutes les modifications du schéma sont terminées. La base de données peut toujours répondre aux écritures et aux requêtes, mais à un débit plus lent.
Nous vous recommandons d'ajouter les index essentiels à votre application métier avant de charger les données. Pour tous les index non critiques, ajoutez-les après la migration des données.
Tester et mesurer le débit
Il peut s'avérer difficile de prédire le débit. C'est pourquoi nous vous recommandons de tester votre stratégie de chargement groupé avant d'exécuter le chargement final. Pour obtenir un exemple détaillé d'utilisation du partitionnement et de surveillance des performances, consultez la page relative à l'optimisation du débit de chargement de données.
Bonnes pratiques relatives au chargement groupé périodique dans une base de données existante
Si vous mettez à jour une base de données existante contenant des données, mais qui ne contient pas les index secondaires, les recommandations de ce document continuent s'appliquent.
Si vous disposez d'index secondaires, ces instructions peuvent quand même vous permettre de bénéficier de performances raisonnables. Celles-ci dépendent du nombre moyen de divisions impliquées dans vos transactions. Si le débit est trop faible, vous pouvez essayer les solutions suivantes :
- Incluez moins de mutations dans chaque commit pour tenter d'augmenter le débit.
- Si la taille de l'importation est supérieure à la taille totale actuelle de la table mise à jour, supprimez les index secondaires, puis rajoutez-les une fois l'opération terminée. Cette étape n'est généralement pas indispensable, mais elle peut améliorer le débit.