Données et bases de données
Oracle ou PostgreSQL : architecture, dialecte SQL et migration
Intermédiaire11 min de lectureMis à jour
Cette page a été traduite de l'anglais avec l'aide de l'IA, puis vérifiée par rapport à l'original. Lire la version anglaise
Oracle et PostgreSQL résolvent le même problème avec des mécanismes différents, et ces différences comptent bien avant le premier cas limite. Ce guide compare leur architecture de processus et de stockage, leur approche du MVCC, leurs dialectes SQL et procéduraux, le partitionnement, la disponibilité et les licences, puis détaille ce qui casse réellement lors d'une migration et comment trancher honnêtement entre les deux.
Ce que vous allez apprendre
- Décrire le modèle instance, base et schéma de chaque moteur et la manière dont les connexions sont servies
- Expliquer la lecture cohérente fondée sur l'undo face au versionnage dans le heap avec vacuum, et le travail d'exploitation qu'implique chacun
- Transposer les constructions SQL et PL/SQL courantes vers leurs équivalents PostgreSQL
- Comparer les options de partitionnement, de réplication et de haute disponibilité, coût des licences compris
- Planifier une migration et repérer les constructions à réécrire plutôt qu'à convertir
On pose généralement la question Oracle contre PostgreSQL comme s'il s'agissait de vitesse. C'est très rarement le cas. Les deux sont des moteurs relationnels matures, à optimiseur fondé sur les coûts et à MVCC, qui absorbent sans peine des charges plus lourdes que celles de la plupart des organisations. Les différences qui comptent sont architecturales et opérationnelles : la façon dont chacun conserve les anciennes versions des lignes, la manière de l'administrer, ce qui se passe quand il faut de la haute disponibilité, et le montant de la facture en fin d'année.
Ce guide compare les deux moteurs tels qu'ils se présentent en 2026 (PostgreSQL 17 et 18, Oracle Database 19c et 23ai) et se termine par le travail de migration que les équipes sous-estiment systématiquement.
Instances, bases et schémas
Oracle trace une frontière nette entre l'instance (les structures mémoire et les processus d'arrière-plan) et la base de données (les fichiers sur disque). L'instance possède la System Global Area, qui contient le buffer cache, la shared pool et le redo log buffer, ainsi qu'un ensemble de processus d'arrière-plan nommés : DBWn écrit les blocs modifiés, LGWR vide le redo, CKPT fait avancer les checkpoints, SMON et PMON assurent la récupération, ARCn archive les redo logs. Depuis la 12c, l'architecture est multitenant : une base conteneur (CDB) héberge des bases enfichables (PDB), et une PDB peut être débranchée d'un conteneur pour être branchée dans un autre, ce qui offre le scénario de mise à niveau et de consolidation le plus propre des deux moteurs. Au sein d'une base, un schéma est un utilisateur : créer un utilisateur crée son schéma, et les objets sont désignés sous la forme owner.object.
PostgreSQL a un cluster : un processus superviseur postgres, un pool de buffers partagé et des processus auxiliaires pour le WAL writer, le checkpointer, le background writer, le lanceur d'autovacuum et les statistiques. Chaque connexion cliente est servie par un processus backend distinct, créé par fork à la connexion. L'établissement d'une connexion est donc relativement coûteux, d'où la présence systématique d'un pooler comme PgBouncer devant toute application qui ouvre et ferme beaucoup de connexions. Un cluster contient plusieurs bases de données, chacune composée de schémas, qui sont des espaces de noms et non des utilisateurs ; une session se connecte à une seule base et ne peut pas faire de jointure entre bases sans postgres_fdw ou dblink. Quand on vient d'Oracle, la correspondance qui fonctionne est la suivante : PDB Oracle ≈ base PostgreSQL, schéma Oracle ≈ schéma PostgreSQL, et la fusion utilisateur/schéma d'Oracle n'existe tout simplement pas.
Deux réponses au MVCC
Les deux moteurs offrent aux lecteurs un instantané cohérent sans bloquer les écrivains. Ils y parviennent différemment, et cette différence explique l'essentiel du contraste dans l'exploitation au quotidien.
Oracle met à jour la ligne sur place et écrit l'image d'avant modification dans un tablespace d'undo. Une requête qui a besoin d'un instantané plus ancien le reconstruit en parcourant l'undo. L'avantage : les tables n'accumulent pas de versions mortes et l'espace est réutilisé automatiquement. Les inconvénients : l'undo est une ressource partagée et finie, et un long rapport peut échouer avec le classique ORA-01555 snapshot too old lorsque l'undo dont il a besoin a été écrasé. La rétention d'undo est un paramètre de réglage qui a un coût réel.
PostgreSQL n'écrase jamais une ligne vivante. Un UPDATE écrit une nouvelle version du tuple dans le heap et marque l'ancienne comme morte ; un DELETE se contente de marquer. Chaque lecteur voit la version visible pour son instantané. Par défaut, rien ne peut échouer avec « snapshot too old », mais les tuples morts doivent être récupérés, et c'est le rôle de vacuum. L'autovacuum s'en charge automatiquement et un système sain n'exige aucune intervention manuelle, mais trois modes de défaillance méritent d'être connus :
- Le bloat des tables. Si l'autovacuum ne suit pas le rythme sur une table très sollicitée en mises à jour, les tuples morts s'accumulent, la table et ses index grossissent, et les parcours lisent plus de pages que nécessaire.
- Les longues transactions bloquent le nettoyage. Une session « idle in transaction » fige l'instantané le plus ancien, si bien que rien de plus récent ne peut être nettoyé, nulle part. Garder des transactions courtes compte encore plus ici que sous Oracle ; voir JDBC et transactions.
- Le rebouclage des identifiants de transaction. La visibilité des lignes repose sur un compteur 32 bits, et vacuum doit périodiquement geler les anciennes lignes. Ignorez les avertissements assez longtemps et la base refusera toute nouvelle écriture pour se protéger.
Les versions récentes ont nettement atténué la douleur : PostgreSQL 17 a réécrit le stockage des tuples morts de vacuum pour consommer beaucoup moins de mémoire et ne plus exiger plusieurs passes sur les index, et PostgreSQL 18 a ajouté un sous-système d'I/O asynchrone qui accélère les grandes lectures séquentielles. Les mises à jour HOT, où une mise à jour ne touchant aucune colonne indexée réutilise la même page, évitent déjà le remaniement des index pour une large part des charges.
Dialecte SQL
Le SQL standard se transpose bien ; les détails, beaucoup moins. Le tableau ci-dessous recense ce qui casse en premier quand une requête écrite pour un moteur s'exécute sur l'autre.
| Point d'attention | Oracle | PostgreSQL |
|---|---|---|
| Type numérique | NUMBER(p,s), un seul type pour tous les nombres | numeric, plus les types natifs integer, bigint, double precision |
| Chaînes | VARCHAR2(n) ; '' est stocké comme NULL | varchar(n), text ; '' est une chaîne vide, distincte de NULL |
| Dates | DATE inclut une heure ; TIMESTAMP WITH TIME ZONE pour les décalages | date n'a pas d'heure ; utilisez timestamptz |
| Limitation des lignes | FETCH FIRST n ROWS ONLY, l'historique ROWNUM | LIMIT n OFFSET m, accepte aussi FETCH FIRST |
| Table factice | SELECT sysdate FROM dual | SELECT now(), sans FROM |
| Valeur de repli pour NULL | NVL, NVL2, DECODE | COALESCE, CASE |
| Casse des identifiants | Les noms sans guillemets passent en MAJUSCULES | Les noms sans guillemets passent en minuscules |
| Hiérarchies | CONNECT BY PRIOR | WITH RECURSIVE (aussi pris en charge par Oracle) |
| Hints de l'optimiseur | Hints /*+ ... */ de première classe | Pas de hints dans les requêtes, par choix ; paramètres du planificateur ou extension pg_hint_plan |
La ligne sur la casse des identifiants provoque bien plus de bugs de migration qu'elle ne le mérite. Un outil qui génère CREATE TABLE "SESSION" à la manière d'Oracle vous condamne aux guillemets doubles et aux majuscules pour toujours sous PostgreSQL. Convertissez les identifiants en minuscules et laissez-les sans guillemets.
Côté procédural, PL/SQL et PL/pgSQL se ressemblent (DECLARE/BEGIN/EXCEPTION/END, curseurs, %ROWTYPE, RAISE) et les routines simples se convertissent presque mécaniquement. Ce sont les écarts structurels qui coûtent du temps :
- Les packages n'ont pas d'équivalent. Un package devient un schéma de fonctions, et l'état au niveau du package devient une table, une table temporaire ou un GUC personnalisé.
- Les transactions autonomes n'existent pas. Les mécanismes de journalisation d'audit qui en dépendaient se reconstruisent avec un background worker, un
dblinkvers la même base, ou en écrivant le journal hors de la transaction. - Les packages
DBMS_se transposent au cas par cas vers des solutions différentes :DBMS_OUTPUTversRAISE NOTICE,DBMS_SCHEDULERverspg_cronou un ordonnanceur externe,UTL_FILEversCOPYcôté serveur ou une extension. - Procédures ou fonctions. Les fonctions PostgreSQL s'exécutent toujours dans la transaction de l'appelant ; seul
CREATE PROCEDURE(à partir de la version 11) peut faire unCOMMIT.
PostgreSQL riposte avec un atout sans équivalent chez Oracle : n'importe quelle fonction peut être écrite dans un autre langage (plpython3u, plv8, Rust ou C) et installée comme extension.
Partitionnement, disponibilité et extensions
Partitionnement. PostgreSQL propose le partitionnement déclaratif depuis la version 10, avec les stratégies par intervalle (range), par liste et par hachage, l'élagage des partitions à la planification comme à l'exécution, les jointures et agrégations partition par partition, et l'attachement ou le détachement de partitions comme simple opération sur les métadonnées. Sa seule limite notable : les index sont propres à chaque partition. Il n'existe pas d'index global, si bien qu'une contrainte d'unicité doit inclure la clé de partitionnement. Le partitionnement d'Oracle est plus ancien, plus riche (interval, reference, system, composite) et gère les index globaux ; mais sur l'Enterprise Edition, c'est une option sous licence séparée, ce qui surprend les équipes qui la croyaient incluse.
Haute disponibilité. Real Application Clusters, chez Oracle, fait tourner plusieurs instances sur un stockage partagé pour une montée en charge active-active et une bascule d'instance ; Data Guard maintient des standbys physiques ou logiques, avec des modes optionnels sans perte de données. PostgreSQL n'a pas de clustering à disque partagé. Il fournit la réplication physique en streaming, avec commit synchrone ou asynchrone et des réplicas en lecture hot standby, ainsi que la réplication logique pour des copies sélectives, entre versions et entre plateformes. La bascule automatique vient de Patroni, de repmgr ou d'un service cloud managé plutôt que du cœur du produit. Les deux modèles atteignent les mêmes objectifs de disponibilité ; un seul est une case à cocher que l'on achète.
Les extensions sont le véritable facteur différenciant de PostgreSQL. pg_stat_statements pour l'empreinte des requêtes, PostGIS pour le géospatial, pgvector pour les embeddings, TimescaleDB pour les séries temporelles, postgres_fdw pour la fédération, pg_partman pour la maintenance des partitions : tout s'installe d'un simple CREATE EXTENSION. Chez Oracle, les équivalents sont intégrés (Spatial, Text, In-Memory column store, Advanced Compression), ce qui est pratique, et soumis à licence séparée, ce qui l'est moins.
Le diagnostic mérite une mention, car les habitudes ne se transposent pas. Les rapports AWR et ASH et les vues V$ d'Oracle sont inégalés pour l'analyse rétrospective, mais exigent le Diagnostics Pack. PostgreSQL expose pg_stat_activity, pg_stat_user_tables, pg_stat_statements et EXPLAIN (ANALYZE, BUFFERS) ; pour l'analyse rétrospective, c'est à vous d'échantillonner ces données dans une stack de monitoring. La lecture des plans de l'un ou l'autre moteur fait l'objet du guide index et plans d'exécution.
Licences et coûts
Oracle Database Enterprise Edition est licencié par cœur de processeur (avec un facteur de cœur) ou par utilisateur nommé, avec un abonnement au support d'environ 22 % du prix de la licence chaque année, et la plupart des fonctionnalités intéressantes (partitionnement, In-Memory, Active Data Guard, packs de diagnostic et de tuning, RAC) sont facturées en sus. La Standard Edition 2 est moins chère, mais plafonnée en nombre de sockets et de threads, et exclut la plupart des options. L'Express Edition est gratuite, avec des limites strictes.
PostgreSQL est distribué sous la PostgreSQL Licence, une licence permissive de type BSD : aucun coût par cœur, aucun audit, aucune fonctionnalité bridée. On dépense tout de même de l'argent (services managés, support commercial, temps d'ingénierie que les fonctionnalités packagées d'Oracle auraient couvert), mais la dépense suit ce que vous utilisez, et non le nombre de cœurs que vous possédez.
Choisir, puis migrer
Choisissez Oracle quand vous avez besoin d'un clustering actif-actif sur stockage partagé à la manière de RAC, quand des charges réglementées dépendent de Flashback Database ou de l'audit fin, quand une application d'éditeur n'est certifiée que sur Oracle, ou quand un vaste patrimoine PL/SQL rend la migration plus coûteuse que les licences. Choisissez PostgreSQL par défaut pour les nouveaux développements : il respecte les standards, reste peu coûteux à faire tourner à toute échelle, est extensible et portable sur tous les clouds. En 2026, la plupart des nouveaux systèmes n'ont aucune exigence que seul Oracle puisse satisfaire.
Si vous migrez, prévoyez quatre chantiers, et admettez d'emblée que les deux derniers dominent :
- Conversion du schéma. Largement automatisée par
ora2pg. Surveillez lesNUMBERsans précision (ne mappez pas tout versnumeric; utilisezbigintouintegerquand les données le permettent), le passage deDATEàtimestampet la casse des identifiants. - Transfert des données. Export massif et
COPYpour une bascule ponctuelle ; réplication logique ou change data capture pour une bascule quasi sans interruption. - Réécriture du code. Packages, transactions autonomes, hints,
CONNECT BY, astuces à base deROWNUMet tout ce qui touche àDBMS_. Il s'agit d'une véritable refonte, pas d'une conversion. - Tests de comportement. La chaîne vide face à NULL est le changement silencieux de données classique ; les conversions implicites qu'Oracle tolérait deviennent des erreurs ; la mise en cache des séquences et
RETURNINGchangent la façon dont les clés générées sont renvoyées. Exécutez la même charge sur les deux moteurs et comparez les résultats avant de comparer les temps.
La qualité du schéma survit au changement dans tous les cas : une conception bien normalisée, comme décrit dans conception de base de données et normalisation, et les habitudes de requêtage du guide des bonnes pratiques SQL s'appliquent aussi bien à l'un qu'à l'autre.
À retenir
- Oracle sépare l'instance de la base, avec des processus d'arrière-plan nommés et des PDB multitenant ; PostgreSQL crée un backend par connexion au sein d'un cluster de bases, ce qui rend un pooler de connexions indispensable.
- La lecture cohérente fondée sur l'undo offre à Oracle une réutilisation automatique de l'espace, au risque d'un
ORA-01555; le versionnage dans le heap de PostgreSQL exige l'autovacuum, et ce sont les longues transactions qui le mettent en échec. - Les différences SQL qui font mal sont la chaîne vide face à NULL, la sémantique de
DATE, la casse des identifiants et la limitation des lignes ; les packages PL/SQL et les transactions autonomes n'ont pas d'équivalent sous PostgreSQL. - Le partitionnement déclaratif de PostgreSQL est solide mais sans index globaux ; celui d'Oracle est plus riche et soumis à licence séparée.
- Oracle vend la haute disponibilité et le diagnostic comme options payantes ; PostgreSQL s'appuie sur la réplication en streaming avec Patroni et sur un écosystème d'extensions qui ne coûte rien à adopter.
- Choisissez PostgreSQL par défaut pour les nouveaux systèmes, Oracle pour des capacités précises que vous savez nommer, et budgétez une migration autour de la réécriture du code et des tests de comportement plutôt que de la conversion du schéma.
Sources et lectures complémentaires
Questions fréquentes
- PostgreSQL peut-il réellement remplacer Oracle en entreprise ?
- Pour la plupart des applications transactionnelles, oui, et ce type de migration est devenu courant. La difficulté ne vient pas des capacités brutes du moteur mais de tout ce qui a été construit autour : des milliers de lignes de packages, des jobs écrits pour DBMS_SCHEDULER, un outillage bâti sur AWR ou une dépendance forte à Real Application Clusters. Évaluez le patrimoine applicatif, pas le moteur, avant de décider : la base elle-même est rarement le point bloquant.
- Pourquoi PostgreSQL a-t-il besoin de VACUUM et pas Oracle ?
- PostgreSQL conserve toutes les versions d'une ligne dans la table elle-même : une ligne mise à jour ou supprimée laisse derrière elle une version morte que seul vacuum peut récupérer. Oracle écrit l'image précédente dans des segments d'undo et écrase la ligne sur place : la réutilisation de l'espace est automatique, mais les longues requêtes peuvent échouer quand l'undo dont elles ont besoin a été écrasé. C'est un autre compromis, pas une fonctionnalité manquante.
- En pratique, PL/SQL et PL/pgSQL sont-ils très différents ?
- La structure en blocs, les curseurs, la gestion des exceptions et les déclarations de variables sont assez proches pour que les procédures simples se convertissent presque ligne à ligne. Les écarts sont structurels : PostgreSQL n'a ni packages, ni transactions autonomes, ni bibliothèque DBMS_ intégrée. Ces éléments demandent une refonte en schémas, background workers ou fonctions d'extension, pas une traduction mécanique.
- Quel moteur est le plus rapide ?
- Aucun, du moins pas d'une manière généralisable. Les deux utilisent un optimiseur fondé sur les coûts, le MVCC et des index B-tree, et tous deux tiennent des charges bien plus lourdes que ce que génèrent la plupart des applications. Dans les systèmes réels, les écarts de performance viennent de la conception du schéma, de l'indexation, de la forme des requêtes et du matériel. Choisissez selon l'adéquation opérationnelle, l'écosystème et le coût, puis mesurez votre propre charge avec vos propres données.