Le blog technique

Toutes les astuces #tech des collaborateurs de PI Services.

#openblogPI

Retrouvez les articles à la une

🦆 DuckDB : Le couteau suisse de l’analytique embarquée !

Vous en avez assez de jongler avec des bases de données lourdes ou de devoir charger vos données dans un entrepôt distant pour la moindre analyse ? Il est temps de découvrir DuckDB, la base de données analytique embarquée qui révolutionne la manière dont les data scientists et les analystes travaillent avec leurs données locales.

Qu’est-ce que DuckDB ?

DuckDB n’est pas une base de données transactionnelle (comme PostgreSQL ou MySQL), mais une base de données orientée colonne (OLAP) conçue spécifiquement pour l’analyse et l’exécution rapide de requêtes complexes (agrégations, jointures, etc.).

Sa particularité majeure est d’être embarquée et sans serveur (serverless). Cela signifie :

  • Elle fonctionne dans le même processus que votre application (Python, R, Node.js, etc.).
  • Elle ne nécessite aucune installation, configuration ou gestion de serveur.
  • Elle peut lire les données directement à partir de fichiers locaux (CSV, Parquet, JSON) sans les importer au préalable.

🚀 L’intérêt majeur : La Vitesse et la Simplicité

  1. ⚡ Vitesse d’exécution : Grâce à son architecture orientée colonne et ses optimisations (vectorisation, compilation just-in-time), DuckDB est souvent plus rapide pour les requêtes analytiques que de nombreux outils traditionnels, y compris pour des jeux de données de plusieurs gigaoctets.
  2. 🔧 Simplicité d’utilisation : Elle utilise le standard SQL que vous connaissez, tout en étant incroyablement facile à intégrer.
  3. 🔗 Zéro ETL (Extract, Transform, Load) : C’est un Data Lakehouse dans une boîte ! Vous pouvez requêter directement des fichiers Parquet ou CSV stockés sur votre disque ou dans le cloud, ce qui élimine la phase fastidieuse de chargement.

🛠️ Exemples d’utilisation concrets avec Python

L’intégration la plus populaire de DuckDB se fait via sa librairie Python.

1. Interroger directement des fichiers (Zero ETL)

Imaginez que vous ayez un gros fichier Parquet nommé ventes_2024.parquet.

Python

import duckdb

# Requête SQL directement sur le fichier Parquet, sans l'importer !
resultat = duckdb.sql("""
    SELECT 
        region, 
        SUM(montant) AS total_ventes
    FROM 
        'ventes_2024.parquet' 
    WHERE 
        date >= '2024-06-01'
    GROUP BY 
        region
    ORDER BY 
        total_ventes DESC;
""")

print(resultat.df())

L’avantage ici est la rapidité : DuckDB ne lira que les colonnes (region, montant, date) et les lignes nécessaires pour la période spécifiée, optimisant l’accès au disque.

2. Remplacer Pandas pour les grandes agrégations

Lorsque votre DataFrame Pandas devient trop volumineux pour la mémoire (ou que les calculs deviennent lents), DuckDB peut prendre le relais sans changer votre flux de travail.

Python

import pandas as pd
import duckdb

# Création d'un DataFrame (peut être très grand)
data_df = pd.DataFrame({
    'cat': ['A', 'B', 'A', 'C', 'B'],
    'val': [10, 20, 15, 50, 30]
})

# Utiliser le DataFrame Pandas directement dans une requête SQL
resultat_sql = duckdb.sql("""
    SELECT 
        cat, 
        AVG(val) 
    FROM 
        data_df 
    GROUP BY 
        cat
""").df()

print(resultat_sql)
#   cat  avg(val)
# 0   A      12.5
# 1   B      25.0
# 2   C      50.0

DuckDB exécute la requête SQL très efficacement sur le DataFrame en mémoire, offrant une alternative rapide et familière à des opérations group by complexes en Pandas.


💡 Conclusion

DuckDB est l’outil parfait pour l’analyse interactive et les flux de travail de prototypage de données. Si vous travaillez régulièrement avec des ensembles de données de taille moyenne à grande (de quelques Mo à plusieurs Go) et que vous avez besoin de la puissance du SQL sans la complexité d’un SGBD serveur, DuckDB est fait pour vous. C’est un véritable « SQLite pour l’analytique » qui mérite sa place dans la boîte à outils de tout professionnel des données !

[Le saviez vous ?] – Trouver la date d’expiration du mot de passe d’un utilisateur

Trouver la date d’expiration du mot de passe dans l’Active Direcotry

Bien souvent j’entends cette question « Sais tu me dire si le mot de passe de l’utilisateur a expiré ?« .

Eh bien oui, il y a un moyen assez facile pour récupérer la date d’expiration du mot de passe d’un utilisateur, pour cela il suffit simplement de faire une requête Active Directory en demandant le retour de l’attribut ‘msDS-UserPasswordExpiryTimeComputed‘.
Voici donc une simple requête Powershell (nécessitant le module AD) pour retourner la date d’expiration du mot de passe d’un utilisateur:

# Samaccountname
$User = "toto"
# Return date
[Datetime]::FromFileTime((Get-ADUser $User -Properties "msDS-UserPasswordExpiryTimeComputed").'msDS-UserPasswordExpiryTimeComputed') 

SCOM – Récupérer les alertes pour tous les objets d’un groupe et leurs descendants

Une question sur le Reddit r/scom a récemment retenu mon attention : comment récupérer de manière récursive toutes les alertes actives pour les membres d’un groupe ainsi que pour les membres de ces membres à l’aide d’une requête SQL, pour pouvoir ensuite insérer le résultat dans un rapport.
La question peut paraitre compliquée mais il existe une table native dans la base OperationsManager qui va permettre une réponse triviale : dbo.RecursiveMembership.

Comme son nom l’indique, cette table contient de manière récursive tous les objets contenus dans un autre objet ainsi que leurs descendants, avec une indication de la profondeur (Depth) d’appartenance:

Il suffit donc de réaliser une simple jointure INNER JOIN entre la table AlertView et la table RecursiveMembership puis de spécifier une clause WHERE basée sur l’Id du groupe parent et le tour est joué!

/****** Change the group display name  ******/
DECLARE @GroupDisplayName AS VARCHAR(255) = 'Your Group display name'

SELECT *
FROM AlertView
INNER JOIN dbo.RecursiveMembership AS RM 
ON AlertView.MonitoringObjectId = RM.ContainedEntityId 
WHERE ((RM.ContainerEntityId = (SELECT BaseManagedEntityId FROM dbo.BaseManagedEntity WHERE DisplayName = @GroupDisplayName)))