Skip to content

Commit

Permalink
proposition d'ajout sur les fichiers parquet (#523)
Browse files Browse the repository at this point in the history
* proposition d'ajout sur les fichiers parquet

* Update 03_Fiches_thematiques/Fiche_import_fichiers_parquet.qmd

* Update 03_Fiches_thematiques/Fiche_import_fichiers_parquet.qmd

---------

Co-authored-by: Lino Galiana <linogaliana@yahoo.fr>
  • Loading branch information
nbc and linogaliana committed Apr 26, 2024
1 parent 4ed3f0b commit d5f7809
Showing 1 changed file with 47 additions and 1 deletion.
48 changes: 47 additions & 1 deletion 03_Fiches_thematiques/Fiche_import_fichiers_parquet.qmd
Expand Up @@ -48,7 +48,8 @@ Le format Parquet présente trois caractéristiques importantes du point de l'ut
knitr::include_graphics("../pics/parquet/stockage_colonne.png")
```

- **Un fichier Parquet contient à la fois les données et des métadonnées**. Ces métadonnées écrites à la fin du fichier enregistrent une description du fichier (appelé **schéma**). Ces métadonnées contiennent notamment le type de chaque colonne (entier/réel/caractère). Ce sont ces métadonnées qui font en sorte que la lecture des données Parquet soit optimisée et sans risque d’altération (voir [ici](https://parquet.apache.org/docs/file-format/metadata/) pour en savoir plus).
- **Un fichier Parquet contient à la fois les données et des métadonnées**. Ces métadonnées écrites à la fin du fichier enregistrent une description du fichier (appelé **schéma**). Ces métadonnées contiennent notamment le type de chaque colonne (entier/réel/caractère) et quelques statistiques (min, max). Ce sont ces métadonnées qui font en sorte que la lecture des données Parquet soit optimisée et sans risque d’altération (voir [ici](https://parquet.apache.org/docs/file-format/metadata/) pour en savoir plus).
- **Un fichier Parquet est composé de groupe de lignes (row group)** contenant également des métadonnées similaires à celles du fichier. La taille idéale d'un row group est de l'ordre de 30 000 à 1 000 000.

Dans un contexte analytique, cette organisation des données génère plusieurs avantages dont les principaux sont:

Expand Down Expand Up @@ -131,6 +132,7 @@ Partitionner un fichier revient à le "découper" selon une clé de partitionnem
- **Il est important de bien choisir les variables de partitionnement** d'un fichier **Parquet**. Il faut choisir des variables faciles à comprendre et qui soient cohérentes avec l'usage des données (année, département, secteur...). En effet, un partitionnement bien construit induit par la suite des gains d'efficacité sur les traitements et facilite la maintenance du fichier sur le long terme.
- **Il est inutile de partitionner des données de petite taille**. Si les données dépassent quelques millions d'observations et/ou si leur taille en CSV dépasse quelques giga-octets, il est utile de partitionner.
- **Il ne faut pas partitionner les données en trop de fichiers**. En pratique, il est rare d'avoir besoin de plus d'une ou deux variables de partitionnement.
- **Si vous souhaitez être compatible avec tous les outils lisant du parquet**, il est recommandé de ne pas partitionner sur une variable pouvant être `NA` ou une chaîne vide.
:::

Pour créer des fichiers **Parquet** partitionnés, il faut utiliser la fonction [`write_dataset()`](https://arrow.apache.org/docs/r/reference/write_dataset.html) du _package_ `arrow`. Voici ce que ça donne sur le fichier de la BPE :
Expand All @@ -150,6 +152,50 @@ Avec cette instruction, on a créé autant de répertoires que de modalités dif
knitr::include_graphics("../pics/parquet/fichier_partition.png")
```

### Données volumineuses: optimiser en triant

Il n'est pas toujours possible ou souhaitable de partitionner un fichier si la variable de partitionnement possède de trop nombreuses modalités (si celle-ci est non discrète ou possède des milliers de modalités...). Dans ces cas là, vous pouvez trier le fichier par la variable à utiliser, cela va permettre une recherche efficace à partir des métadonnées des fichiers et des groupes de lignes.

```{r, eval = FALSE}
donnees_BPE |>
arrange(EPCI) |>
write_parquet(
sink = "Data_parquet/BPE_ENS.parquet"
)
```

Vous pouvez bien sûr cumuler les partitions avec des tris :

```{r, eval = FALSE}
donnees_BPE |>
arrange(EPCI) |>
write_dataset(
path = "Data/",
partitioning = c("REG"), # la variable de partitionnement
format="parquet"
)
```

Cette méthode est quasiment aussi efficace que le partitionnement.

### Vérifier qu'un fichier parquet est correctement optimisé

Dans certains cas pathologiques quand vous manipulez de très gros volumes de données (par exemple quand vous partitionnez avec `arrow::open_dataset` un volume de données de plusieurs de dizaine de millions de lignes), le package `arrow` peut générer des fichiers parquet avec un nombre de lignes par row group très petite (inférieur à 1000 voire à 100). Cela rendra toutes les requêtes sur vos fichiers extrèmement lent.

Pour vérifier que vos fichiers ont une taille de row group correcte, vous pouvez utiliser la fonction suivante :

```{r, eval = FALSE}
library(arrow)
mean_row_group_size <- function(path) {
a <- arrow::ParquetFileReader$create(path)
(a$num_rows / a$num_row_groups)
}
mean_row_group_size('bpe2018/REG=11/part-0.parquet')
```

Vous devez obtenir une valeur au moins égale à 10 000. Si vous obtenez une valeur inférieure, vous aurez intérêt à regénérer votre fichier en passant par d'autres méthodes (par exemple générer chaque partition en faisant une boucle et un filtre).

## Lire et exploiter un fichier Parquet avec `R` {#readparquet}

### Cas des données peu volumineuses: importer les données en mémoire
Expand Down

0 comments on commit d5f7809

Please sign in to comment.