veilletech.fr
20 oct. Feed du jour
#07 LARAVEL Article

Laravel : DB::olap() contourne les 100 000 lignes

OLAP pour l'export de ce soir, pas pour vos pages.

Laravel 13.36 ajoute DB::olap(), qui passe une connexion MySQL en mode OLAP de Vitess le temps d'un callback pour dépasser les limites de PlanetScale (100 000 lignes et 64 Mio par requête). Elle règle le mode sur les connexions en écriture et en lecture, revient en OLTP ensuite et ne fait rien hors Vitess. Piège : une LazyCollection (cursor, lazy, lazyById) exécute sa requête plus tard, déjà en OLTP.

3 min de lectureintermédiairevidéo 1:27
Partager
Sommaire6 sections
  1. Ce qui se passe
  2. Avant : une instruction brute et un finally
  3. Maintenant
  4. Le piège des collections paresseuses
  5. Les limites
  6. À retenir

Ce qui se passe

Les bases MySQL de PlanetScale reposent sur Vitess, qui limite par défaut, dans son mode de charge OLTP, chaque requête : 100 000 lignes lues, modifiées ou supprimées au maximum, et un résultat de 64 Mio au plus. Un rapport ou un export CSV sur une grosse table peut donc échouer, alors que la même requête passe sur un MySQL local. Vitess a un second mode, OLAP, sans ces limites. Laravel 13.36 ajoute DB::olap(), qui y bascule une connexion le temps d'un callback.

Avant : une instruction brute et un finally

Le contournement passait par set workload = 'olap', à remettre en 'oltp' dans un bloc finally. Deux défauts : l'instruction part sur la connexion en écriture, alors qu'un select peut être envoyé à un réplica resté en OLTP ; et sans finally, le prochain job d'un worker de file, ou la requête suivante sous Octane, hérite de la connexion en OLAP.

Maintenant

olap(), ajoutée à la classe de connexion MySQL par Jack Bayliss (PR #61932), règle le mode sur les connexions en écriture et en lecture (en connectant d'abord la lecture si besoin), exécute le callback, puis revient en OLTP dans un finally. Elle renvoie ce que renvoie le callback. Hors Vitess, elle appelle simplement le callback et ne fait rien d'autre, donc le même code tourne en local, en CI et sur PlanetScale. La même PR ajoute isVitess(), qui renvoie vrai si la version du serveur contient Vitess ou PlanetScale, et qui doit se connecter pour la lire, comme isMaria().

Le piège des collections paresseuses

Le mode redevient OLTP dès que le callback rend la main. Or cursor(), lazy() et lazyById() renvoient une LazyCollection dont la requête ne part qu'à l'itération :

PHP
// Mauvais : la requête part après le retour d'olap(), donc en OLTP
$orders = DB::olap(fn () => Order::query()->cursor());

// Bon : on parcourt à l'intérieur du callback (ou on appelle get())
DB::olap(function () {
    Order::query()->lazyById(5000)->each(fn ($order) => exporter($order));
});

Le billet détaille aussi un job de file qui écrit un export CSV entièrement dans le callback ; la forme ci-dessus en reprend l'idée.

Les limites

Source : Run Large PlanetScale Queries in Laravel With DB::olap(), Laravel News, 19 octobre 2026. Source en anglais. La fonction avait été citée en une ligne dans la fiche Laravel 13.36 du 15 octobre.