The Daily Commit · Édition de rubrique La une PHP AI Dev EN DE FR ES

The Php Times

Lectures — Écosystème

Queue-SQL : un package qui répartit les UPDATE et DELETE massifs de Laravel sur des jobs parallèles


Queue-SQL, un package Laravel de Kamran Atayev, découpe les UPDATE et DELETE volumineux en tranches de clés primaires traitées en parallèle via le batching natif de Laravel.

LARAVEL NEWS, 28 juillet 2026 sélectionné par Sönke

Il propose une macro queue(), un suivi CLI, un aperçu dry-run et du tagging Horizon ; il requiert PHP 8.1+ et Laravel 10 à 13.

Exécuter un UPDATE ou un DELETE unique sur des millions de lignes peut bloquer la base pendant des minutes, faire prendre du retard aux réplicas ou expirer en plein déploiement. Queue-SQL, un package Laravel de Kamran Atayev, y répond en découpant les grosses écritures en jobs parallèles : il détermine les clés primaires minimale et maximale de la requête, découpe cette plage d'ID en tranches bornées et envoie un Illuminate\Bus\Batch qui traite chaque tranche indépendamment.

Le package enregistre une macro queue() sur le Query Builder et Eloquent, exposant update, delete, insert et upsert. Les contraintes sont compilées en fragments SQL et bindings, si bien que closures imbriquées, whereHas, whereExists et sous-requêtes parviennent aux workers sans problème de sérialisation. Le dimensionnement des jobs se fait via chunk (lignes par job) ou maxJobs (nombre total cible sur la plage de clés) ; les deux combinés déclenchent une InvalidArgumentException. dispatch() retourne un Illuminate\Bus\Batch natif avec then, catch, finally et allowFailures.

L'usage consiste à chaîner queue() avant la méthode d'écriture et à terminer par dispatch() — rien n'est mis en file avant. Exemple : Order::where('status', 'complete')->queue(chunk: 25000, tries: 2, onQueue: 'maintenance', throttle: 4)->update(['status' => 'completed'])->dispatch(). L'option throttle limite les jobs par seconde, protégeant connexions et réplicas lors des gros backfills. Les suppressions utilisent la même syntaxe ; les insertions en masse ignorent la planification par plage de clés et répartissent le tableau d'enregistrements entre les jobs.

Comme chaque job d'update ou de delete cible une tranche de clés fixe, les retries sont idempotents. Ce n'est pas le cas des insertions, qui peuvent créer des doublons — la documentation recommande un index unique ou upsert() quand la sûreté des retries compte. Comparé au trait Prunable et à la commande model:prune de Laravel, qui suppriment séquentiellement dans un seul processus, Queue-SQL fonctionne en parallèle, suit la progression en batch et gère aussi les updates arbitraires et les insertions en masse.

Remplacer dispatch() par dryRun() prévisualise le plan de batching (opération, table, nombre de jobs, plages, lignes estimées) sans rien mettre en file. Le découpage par plage de clés repose sur les valeurs min/max des clés plutôt que sur des comptages exacts : sur les tables avec de grands trous d'ID, certains jobs traitent moins de lignes, mais le nombre total de jobs reste fixe.

La CLI surveille les batches directement dans la table des batches du framework : queue-sql:status liste ou inspecte les batches, queue-sql:cancel en annule un, --watch rafraîchit toutes les deux secondes dans les terminaux interactifs (une seule fois en non-interactif), et --json formate la sortie. Le statut affiche jobs totaux, en attente et échoués, pourcentages de progression et état du batch. Sous Horizon, les jobs sont automatiquement tagués avec queue-sql, le type d'opération et les tables cibles. Les valeurs par défaut (taille de chunk, retries, backoff, throttling, délais, noms de files) se configurent dans config/queue-sql.php.

Le package exige PHP 8.1+ et Laravel 10 à 13, avec SQLite, MySQL et PostgreSQL. Installation via composer require kamranata/queue-sql, puis queue:batches-table et migrate, car il s'appuie sur le batching natif. Deux limites : le découpage exige une clé primaire entière auto-incrémentée (sinon la requête part dans un job unique), et les bornes de clés sont figées au moment du dispatch() — les lignes insérées ensuite avec des ID supérieurs ne sont pas couvertes. Un script de benchmark (benchmarks/lock_duration.php) est fourni ; lors d'un test de suppression de 20 000 lignes sous SQLite, un DELETE non batché a tenu son verrou 3,6 fois plus longtemps que le plus long verrou mesuré par Queue-SQL.

Lire la source originale (en anglais) ↗

Évaluer cet article : 0

Tribune des lecteurs

Pas encore de contributions — lance le débat.

← Écosystème — Page B1

"All the Code That's Fit to Ship" · The Daily Commit · Édition écran · Mentions légales · Politique de confidentialité