J'utilise Python pour charger les données dans les tables BigQuery. J'ai besoin de mettre à jour certaines lignes modifiées dans ces tables. Mais je n'arrivais pas à comprendre comment les mettre à jour correctement? J'en veux fonction UPSERT
similaire - insérer une ligne uniquement si elle n'existe pas, sinon - mettre à jour la ligne existante.
Est-ce la bonne façon d'utiliser un champ spécial avec une somme de contrôle dans les tableaux (et de comparer la somme dans le processus de chargement)? S'il y a une bonne idée, comment résoudre ce problème avec Python? (Comme je le sais, il ne peut pas mettre à jour les données existantes)
Veuillez m'expliquer, quelle est la meilleure pratique?
BigQuery est par conception uniquement préféré. Cela signifie que vous feriez mieux de laisser les lignes en double de la même entité dans la table et d'écrire vos requêtes pour toujours lire la ligne la plus récente.
La mise à jour des lignes comme vous le savez dans les tables transactionnelles n'est pas possible dans BQ. Vous n'avez que 100 mises à jour par table et par jour. C'est très limité et leur objectif est totalement différent.
Étant donné que BQ est utilisé comme lac de données, vous devez simplement diffuser de nouvelles lignes chaque fois que l'utilisateur, par exemple: met à jour son profil. Vous finirez par avoir de 20 enregistre 20 lignes pour le même utilisateur. Plus tard, vous pouvez rematérialiser votre table pour avoir des lignes uniques en supprimant les données en double.
Voir la plus grande question pour la suite: BigQuery - instruction DELETE pour supprimer les doublons
BigQuery prend désormais en charge MERGE
, qui peut combiner à la fois INSERT
et UPDATE
en une seule opération atomique, c'est-à-dire UPSERT
.
En utilisant les exemples de tableaux de Mikhail, cela ressemblerait à:
MERGE merge_example.table_data T
USING merge_example.table_changes S
ON T.id = S.id
WHEN MATCHED THEN
UPDATE SET value = s.value
WHEN NOT MATCHED THEN
INSERT (id, value) VALUES(id, value)
Voir ici .
BigQuery ne prend pas directement en charge UPSERT
, mais si vous en avez vraiment besoin - vous pouvez utiliser UPDATE
et INSERT
l'un après l'autre pour obtenir le même résultat. Voir l'exemple simplifié ci-dessous
Supposons que vous ayez deux tableaux comme ci-dessous - celui qui contient vos données (yourproject.yourdadtaset.table_data
) et un autre (yourproject.yourdadtaset.table_changes
) qui contient les modifications que vous souhaitez appliquer à la première table
Maintenant, les requêtes ci-dessous s'exécutent l'une après l'autre.
Mettre à jour la requête:
#standardSQL
UPDATE `yourproject.yourdadtaset.table_data` t
SET t.value = s.value
FROM `yourproject.yourdadtaset.table_changes` s
WHERE t.id = s.id
Et maintenant - INSERT Query
#standardSQL
INSERT `yourproject.yourdadtaset.table_data` (id, value)
SELECT id, value
FROM `yourproject.yourdadtaset.table_changes`
WHERE NOT id IN (SELECT id FROM `yourproject.yourdadtaset.table_data`)
avec comme résultat (et nous avons terminé ici)
J'espère que l'exemple est simple et clair, afin que vous puissiez l'appliquer dans votre cas
Je suis peut-être en retard pour cela, mais vous pouvez effectuer upsert dans BigQuery en utilisant Dataflow/Apache Beam. Vous pouvez effectuer un CoGroupByKey pour obtenir des valeurs partageant la clé commune à partir des deux sources de données (l'une étant la table de destination) et mettre à jour les données lues à partir de la table BQ de destination. Enfin, chargez les données en mode de chargement tronqué. J'espère que cela t'aides.
De cette façon, vous évitez toutes les limites de quota dans BigQuery et effectuez toutes les mises à jour dans Dataflow.