Passer au contenu principal

⚖️ SQL vs NoSQL

📖 Définition

SQL (bases de données relationnelles) stocke les données dans des tables structurées et les manipule avec le langage SQL. NoSQL (bases de données non-relationnelles) stocke des données de différentes formes avec un schéma flexible et est avantageux pour l'extension horizontale. Chacun a ses avantages et inconvénients, et doit être choisi selon les besoins du projet.

🎯 Comprendre par l'analogie

Bibliothèque vs Entrepôt

SQL (BD relationnelle) = Bibliothèque organisée
├─ Tous les livres sont classés à des emplacements déterminés
├─ Informations précises enregistrées sur les fiches
├─ Règles strictes d'emprunt/retour
└─ Facile à trouver mais peu flexible

NoSQL (BD non-relationnelle) = Entrepôt flexible
├─ Peut stocker des objets de différentes formes
├─ Ajout/suppression rapides
├─ Extension d'espace facile
└─ Flexible mais peut être difficile à organiser

Registre scolaire vs Réseaux sociaux

SQL = Registre de présence scolaire
Table étudiants:
┌────┬─────────┬─────┬────────┐
│ ID │ Nom │ Âge │ Classe │
├────┼─────────┼─────┼────────┤
│ 1 │ Pierre │ 15 │ 1A │
│ 2 │ Marie │ 15 │ 2A │
└────┴─────────┴─────┴────────┘
- Tous les étudiants ont les mêmes champs

NoSQL = Profil de réseau social
Utilisateur1: { name: "Pierre", age: 15, hobbies: ["lecture", "jeux"] }
Utilisateur2: { name: "Marie", city: "Paris", job: "étudiant", pets: 2 }
- Chaque utilisateur peut avoir des informations différentes

⚙️ Principe de fonctionnement

1. Comparaison des structures de données

-- SQL: Tables structurées
Table users
┌────┬─────────┬──────────────────┬─────┐
│ id │ name │ email │ age │
├────┼─────────┼──────────────────┼─────┤
1 │ Pierre │ pierre@mail.com25
2 │ Marie │ marie@mail.com30
└────┴─────────┴──────────────────┴─────┘

Table orders
┌────┬─────────┬─────────────┬───────┐
│ id │ user_id │ product │ price │
├────┼─────────┼─────────────┼───────┤
11 │ Ordinateur │ 1500
21 │ Souris │ 30
└────┴─────────┴─────────────┴───────┘
// NoSQL: Documents flexibles
// Exemple MongoDB
{
_id: ObjectId("507f1f77bcf86cd799439011"),
name: "Pierre",
email: "pierre@mail.com",
age: 25,
orders: [ // Documents imbriqués
{
product: "Ordinateur",
price: 1500,
date: "2024-01-15"
},
{
product: "Souris",
price: 30,
date: "2024-01-20"
}
],
preferences: { // Structures variées
theme: "dark",
notifications: true
}
}

2. Types de bases de données NoSQL

1. Document DB (orientée document)
└─ MongoDB, CouchDB
└─ Stockage de documents JSON

2. Key-Value DB (clé-valeur)
└─ Redis, DynamoDB
└─ Cache rapide, stockage de sessions

3. Column-Family DB (orientée colonnes)
└─ Cassandra, HBase
└─ Analyse de données à grande échelle

4. Graph DB (graphe)
└─ Neo4j, Amazon Neptune
└─ Données centrées sur les relations (réseaux sociaux)

💡 Exemples pratiques

Exemple SQL (MySQL)

-- Création de tables (schéma strict)
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
age INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
product VARCHAR(100),
price DECIMAL(10, 2),
FOREIGN KEY (user_id) REFERENCES users(id)
);

-- Insertion de données
INSERT INTO users (name, email, age)
VALUES ('Pierre', 'pierre@mail.com', 25);

-- Récupération avec JOIN
SELECT
users.name,
orders.product,
orders.price
FROM users
INNER JOIN orders ON users.id = orders.user_id
WHERE users.name = 'Pierre';

-- Transaction (garantie ACID)
BEGIN TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

Exemple NoSQL (MongoDB)

// Pas de schéma - structure libre
db.users.insertOne({
name: "Pierre",
email: "pierre@mail.com",
age: 25,
orders: [
{ product: "Ordinateur", price: 1500 },
{ product: "Souris", price: 30 }
]
});

// Structure différente possible !
db.users.insertOne({
name: "Marie",
email: "marie@mail.com",
hobbies: ["lecture", "voyage"], // Champs différents
address: { // Objet imbriqué
city: "Paris",
zipcode: "75001"
}
});

// Recherche
db.users.find({ name: "Pierre" });

// Recherche dans document imbriqué
db.users.find({
"orders.product": "Ordinateur"
});

// Mise à jour
db.users.updateOne(
{ name: "Pierre" },
{
$set: { age: 26 },
$push: {
orders: { product: "Clavier", price: 80 }
}
}
);

// Agrégation
db.users.aggregate([
{ $unwind: "$orders" },
{ $group: {
_id: "$name",
totalSpent: { $sum: "$orders.price" }
}
}
]);

SQL vs NoSQL dans Node.js

// ============ SQL (MySQL) ============
const mysql = require('mysql2/promise');

const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'password',
database: 'myapp'
});

// Récupérer utilisateur avec commandes (JOIN nécessaire)
async function getUserWithOrders(userId) {
const [rows] = await pool.execute(`
SELECT
users.name,
users.email,
orders.product,
orders.price
FROM users
LEFT JOIN orders ON users.id = orders.user_id
WHERE users.id = ?
`, [userId]);

return rows;
}

// ============ NoSQL (MongoDB) ============
const { MongoClient } = require('mongodb');

const client = new MongoClient('mongodb://localhost:27017');
const db = client.db('myapp');
const users = db.collection('users');

// Récupérer utilisateur avec commandes (JOIN inutile - déjà inclus)
async function getUserWithOrders(userId) {
const user = await users.findOne({ _id: userId });
// Les informations de commande sont déjà dans user.orders !
return user;
}

Exemple pratique: Système de blog

// ============ Approche SQL ============
// Structure normalisée
/*
Table posts:
id, title, content, author_id, created_at

Table comments:
id, post_id, user_id, content, created_at

Table tags:
id, name

Table post_tags:
post_id, tag_id
*/

// Récupération article + commentaires + tags → Plusieurs JOIN nécessaires
SELECT
posts.*,
comments.content as comment,
tags.name as tag
FROM posts
LEFT JOIN comments ON posts.id = comments.post_id
LEFT JOIN post_tags ON posts.id = post_tags.post_id
LEFT JOIN tags ON post_tags.tag_id = tags.id
WHERE posts.id = 1;

// ============ Approche NoSQL ============
// Structure dénormalisée
{
_id: ObjectId("..."),
title: "Introduction à MongoDB",
content: "MongoDB est...",
author: {
id: "user123",
name: "Pierre"
},
comments: [
{
user: { id: "user456", name: "Marie" },
content: "Excellent article !",
createdAt: "2024-01-15"
}
],
tags: ["base de données", "NoSQL"],
createdAt: "2024-01-10"
}

// Récupération de toutes les données en une seule requête !
db.posts.findOne({ _id: ObjectId("...") });

🤔 Questions fréquentes

Q1. Lequel choisir ?

R: Choisissez selon les caractéristiques du projet :

✅ Choisir SQL dans les cas suivants :
├─ Structure de données claire et fixe
├─ Relations complexes et nombreux JOIN
├─ Transactions ACID essentielles (finance, e-commerce)
├─ Intégrité des données importante
└─ Ex : Système bancaire, logiciel comptable, ERP

✅ Choisir NoSQL dans les cas suivants :
├─ Structure de données fluide
├─ Lecture/écriture rapide importante
├─ Extension horizontale (scale out) nécessaire
├─ Traitement de données volumineuses
└─ Ex : Réseaux sociaux, IoT, analyse temps réel, logs

Q2. Quelles sont les principales différences ?

R:

CaractéristiqueSQLNoSQL
Structure de donnéesTables (lignes, colonnes)Documents, clé-valeur, graphes, etc.
SchémaFixe (strict)Flexible (dynamique)
ExtensionExtension verticale (Scale Up)Extension horizontale (Scale Out)
RelationsConnexion par JOINImbrication ou référence
TransactionGarantie ACIDCohérence éventuelle (BASE)
RequêtesLangage SQLDifférent pour chaque BD
ExemplesMySQL, PostgreSQLMongoDB, Redis
// SQL: ACID
Atomicity (Atomicité): Tout ou rien
Consistency (Cohérence): Pas de violation des règles
Isolation (Isolation): Indépendance entre transactions
Durability (Durabilité): Stockage permanent

// NoSQL: BASE
Basically Available (Disponibilité de base)
Soft state (État souple)
Eventually consistent (Cohérence éventuelle)

Q3. Différences de performance ?

R: Cela dépend du modèle d'utilisation :

// Avantage SQL: Requêtes complexes, JOIN
// Combinaison de données de plusieurs tables
SELECT u.name, p.title, c.content
FROM users u
JOIN posts p ON u.id = p.author_id
JOIN comments c ON p.id = c.post_id
WHERE u.age > 20
ORDER BY p.created_at DESC;
// → Puissant et précis mais peut être lent

// Avantage NoSQL: Lecture/écriture rapide
// Toutes les informations dans un seul document
db.posts.find({ author_age: { $gt: 20 } })
.sort({ created_at: -1 });
// → Très rapide mais JOIN complexes difficiles

// Exemple de benchmark
SQL: 10 000 lectures/sec (JOIN complexes)
NoSQL: 100 000 lectures/sec (recherche simple)

SQL: 5 000 écritures/sec (garantie transaction)
NoSQL: 50 000 écritures/sec (écriture rapide)

Q4. Peut-on les utiliser ensemble ?

R: Oui ! C'est appelé Polyglot Persistence :

// Ex : Système e-commerce

// 1. SQL (MySQL) - Commandes, paiements
// → Transactions ACID essentielles
{
orders: "MySQL",
payments: "PostgreSQL",
inventory: "MySQL"
}

// 2. NoSQL (MongoDB) - Catalogue produits
// → Attributs flexibles, recherche rapide
{
products: "MongoDB",
reviews: "MongoDB"
}

// 3. NoSQL (Redis) - Cache, sessions
// → Lecture/écriture ultra-rapide
{
cache: "Redis",
sessions: "Redis",
realtime: "Redis"
}

// 4. Graph DB (Neo4j) - Système de recommandation
// → Requêtes basées sur les relations
{
recommendations: "Neo4j",
socialGraph: "Neo4j"
}

Q5. La migration est-elle difficile ?

R: C'est possible avec une approche stratégique :

// Stratégie de migration SQL → NoSQL

// 1. Approche hybride
// - Nouvelles fonctionnalités en NoSQL
// - Maintien des fonctionnalités existantes en SQL

// 2. Migration progressive
// Étape 1: Commencer par les données en lecture seule
// Étape 2: Fonctionnalités moins critiques
// Étape 3: Fonctionnalités principales

// 3. Synchronisation des données
// - Capture des données modifiées (CDC)
// - Streaming d'événements (Kafka)

// Ex : Double écriture
async function createUser(userData) {
// Écriture en SQL
const sqlUser = await mysqlDB.insert(userData);

// Écriture aussi en NoSQL (asynchrone)
await mongooDB.insertOne({
...userData,
_id: sqlUser.id
}).catch(err => {
// SQL maintenu même en cas d'échec
console.error('Échec de sync MongoDB:', err);
});

return sqlUser;
}

🎓 Prochaines étapes

Après avoir compris SQL et NoSQL, apprenez :

  1. Qu'est-ce qu'une base de données ? - Concepts de base
  2. Qu'est-ce que Node.js ? - Développement backend
  3. Qu'est-ce que Docker ? (documentation à venir) - Conteneurisation de bases de données

Mise en pratique

# ============ Pratique MySQL ============
# Installation
brew install mysql # macOS

# Exécution
mysql -u root -p

# Création de tables et requêtes
CREATE DATABASE testdb;
USE testdb;
CREATE TABLE users (id INT, name VARCHAR(50));
INSERT INTO users VALUES (1, 'Pierre');
SELECT * FROM users;

# ============ Pratique MongoDB ============
# Installation
brew tap mongodb/brew
brew install mongodb-community

# Exécution
mongod --config /usr/local/etc/mongod.conf

# MongoDB Shell
mongosh

# Insertion et recherche de données
use testdb
db.users.insertOne({ name: "Pierre", age: 25 })
db.users.find()

🎬 Conclusion

SQL et NoSQL ont chacun leurs avantages et inconvénients :

  • SQL : Données structurées, transactions ACID, relations complexes
  • NoSQL : Schéma flexible, performances rapides, extension horizontale
  • Critères de choix : Structure des données, extensibilité, exigences de cohérence
  • Polyglotte : Utiliser plusieurs BD selon les besoins

"Il n'y a pas de solution miracle" - Choisissez la base de données adaptée à votre projet ! ⚖️✨