Python et Postgres : arrêtez de tirer la table en mémoire
Le SQL peut être juste et l’API meurt quand même : .all() sans borne, requêtes en f-string, N+1 de l’ORM, une connexion neuve par requête, pandas comme entrepôt sur la boîte web. Comment je garde Python mince autour de Postgres en 2026.
L’article SQL, c’est la requête. Ici, le Python qui refuse de l’annuler. Je revois le même accident : une route FastAPI propre, un modèle SQLAlchemy propre, et 200 Mo de working set parce que scalars().all() voulait dire « tout ». La base a fait son travail. L’app a demandé un CSV de l’entrepôt.
J’ai déjà écrit les cinq formes SQL que j’utilise à la place d’une boucle. Ici, l’enveloppe : des paramètres, un pool, un timeout, et la discipline de ne pas collecter une table parce que l’API dataframe est commode.
1. Le script qui marchait sur 800 lignes
Dump local, pandas, un groupby, un to_excel. Puis quelqu’un le pointe sur la prod « juste pour ce rapport ». Ce n’est pas un rapport. C’est un extrait de la base primaire dans un process que l’OOM va tuer. Si la réponse est un nombre, une liste de cinquante lignes, ou un fichier que vous pouvez streamer, ne collectez pas la table. J’écris l’agrégation en SQL — ou une vue matérialisée si c’est quotidien — et je garde Python comme enveloppe : auth, paramètres, format.
2. Les f-strings ne sont pas une API de requête
Construire SELECT * FROM orders WHERE id = {order_id} avec une f-string, c’est offrir la base. Utilisez $1, %(id)s, ou des paramètres liés. Chaque driver les a. SQLAlchemy text() aussi. Un LLM qui concatène du SQL, c’est le même bug avec de meilleures manières. Même famille : des listes IN en joignant des chaînes. Utilisez ANY($1::int[]) ou un vrai bind. Je ne « m’échappe » pas de ça.
3. Le N+1 de l’ORM qui a l’air d’un Python propre
for invoice in invoices : invoice.customer.name, c’est une requête de plus par ligne. selectinload, une jointure, ou une requête de liste dédiée. « J’ajouterai un loader plus tard », c’est comme ça que la page liste meurt après un salon. J’utilise un ORM pour les écritures qui collent à l’unité de travail — créer commande et lignes dans une session. Du SQL pour les listes et les exports. L’hybride n’est pas un échec. Un ORM qui cache quatre cents requêtes, si.
4. Une connexion par requête n’est pas un pool
Ouvrir psycopg dans chaque handler, ou créer un engine dans la fonction, c’est comme ça que vous tapez max_connections pendant un déploiement. Un engine ou un pool async par process. Un timeout à l’acquire. Un checkout qui ne doit pas vivre à travers un await vers un autre service. asyncpg ou psycopg 3 sur le chemin chaud que je contrôle. SQLAlchemy si l’équipe pense déjà en sessions et qu’il me faut migrations plus identity map. Je ne démarre pas trois ORM parce qu’un tuto utilisait Django.
5. Pandas est une deuxième base — traitez-le comme tel
Un groupby pandas sur un frame de deux gigaoctets, c’est une requête d’entrepôt sur une boîte API. S’il vous faut pandas, l’extrait doit déjà être étroit : les colonnes que vous utilisez, le jour dont vous avez besoin, un COPY ou un curseur côté serveur. chunksize existe. fetchmany existe. yield existe. J’aime pandas dans les notebooks d’analyse. Je ne l’aime pas comme implémentation de /stats. Cette route, c’est du SQL plus un dict typé.
6. Ce que je livre vraiment
Un routeur FastAPI. Des paramètres validés — dates, id d’espace, une limite. Une fonction qui lance une requête paramétrée, souvent les formes de fenêtre de l’autre article. Un pool. Un statement timeout pour qu’un mauvais plan tue la requête, pas l’instance. Pas de SELECT *. Pas de .all() silencieux sur une table sans borne. Une requête, une transaction, sauf raison nommée — outbox, un passage de paiement. L’isolation reste READ COMMITTED jusqu’à ce que je puisse nommer l’anomalie que je crains.
Conclusion : la colle oui, un second entrepôt non
Python est la meilleure colle que j’ai pour HTTP et les jobs. Il devient cher quand il joue à Postgres. Écrivez la requête, liez les paramètres, streamez ou agrégez, et gardez le process petit. La boucle maline peut attendre. La base en avait déjà une meilleure — c’est l’autre article.
On discute de votre projet ?
Je suis ingénieure web senior, spécialisée en React et Next.js - disponible en freelance partout dans le monde.
Localisation
Kyiv, Ukraine
Upwork
Voir le profilTelegram
Me contacterViber
Me contacter