← Назад к вопросам

В чем разница между PostgreSQL и MongoDB?

2.3 Middle🔥 191 комментариев
#Базы данных и SQL#Кэширование и NoSQL

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

PostgreSQL vs MongoDB: различия и применение

PostgreSQL и MongoDB — это два кардинально различных подхода к хранению данных. PostgreSQL — реляционная СУБД (RDBMS), а MongoDB — документоориентированная NoSQL база данных. Выбор между ними зависит от структуры данных и требований приложения.

Основные типы

PostgreSQL:

  • Реляционная база данных (RDBMS)
  • Хранит данные в таблицах с фиксированной схемой
  • SQL запросы
  • ACID транзакции

MongoDB:

  • Документоориентированная база данных (NoSQL)
  • Хранит данные как JSON-документы с гибкой схемой
  • Запросы на JavaScript
  • ACID транзакции (с версии 4.0)

1. Модель данных

PostgreSQL — таблицы и отношения:

-- Определяем схему
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) UNIQUE,
    age INT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    user_id INT NOT NULL REFERENCES users(id),
    amount DECIMAL(10, 2),
    created_at TIMESTAMP
);

-- Вставляем данные
INSERT INTO users (name, email, age) VALUES (John, john@example.com, 30);
INSERT INTO orders (user_id, amount) VALUES (1, 99.99);

-- JOIN для связанных данных
SELECT u.name, o.amount 
FROM users u
JOIN orders o ON u.id = o.user_id;

MongoDB — документы с гибкой структурой:

// Нет предварительной схемы, просто добавляем документы
db.users.insertOne({
    name: "John",
    email: "john@example.com",
    age: 30,
    createdAt: new Date(),
    // Документ может содержать другие поля без изменения схемы
    address: {
        city: "New York",
        zipCode: "10001"
    }
});

// Встроенные данные (denormalization)
db.orders.insertOne({
    user_id: ObjectId("..."),
    amount: 99.99,
    user: {  // Копируем данные пользователя
        name: "John",
        email: "john@example.com"
    },
    createdAt: new Date()
});

// Поиск (автоматически выполняется lookup)
db.orders.findOne({ "user._id": ObjectId(...) });

2. Схема данных

PostgreSQL: фиксированная схема (Rigid)

-- Схема определена строго
CREATE TABLE products (
    id INT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    price DECIMAL(10, 2) NOT NULL,
    category VARCHAR(50)
);

-- Изменение схемы требует ALTER TABLE
ALTER TABLE products ADD COLUMN description TEXT;

MongoDB: гибкая схема (Flexible)

// Первый документ
db.products.insertOne({
    name: "Laptop",
    price: 999.99
});

// Второй документ с другой структурой
db.products.insertOne({
    name: "Mouse",
    price: 29.99,
    color: "black",  // Новое поле
    specs: {          // Вложенная структура
        dpi: 3200,
        buttons: 5
    }
});

// Нет ошибки, оба документа сохраняются

3. Стоимость операций

PostgreSQL: JOIN операции

-- Нормализованная структура (Normal Form)
-- Требует JOIN для получения связанных данных
SELECT u.id, u.name, u.email,
       o.id as order_id, o.amount,
       p.id as product_id, p.name as product_name
FROM users u
JOIN orders o ON u.id = o.user_id
JOIN order_items oi ON o.id = oi.order_id
JOIN products p ON oi.product_id = p.id
WHERE u.id = 1;

-- Сложные JOIN с большими таблицами могут быть медленными

MongoDB: встроенные документы (Denormalization)

// Документ содержит все необходимые данные
db.orders.findOne({ _id: ObjectId(...) });

Result:
{
    _id: ObjectId(...),
    user: {
        id: 1,
        name: "John",
        email: "john@example.com"
    },
    items: [
        {
            productId: 101,
            productName: "Laptop",
            quantity: 1,
            price: 999.99
        }
    ],
    totalAmount: 999.99,
    createdAt: new Date()
}

// Один запрос вместо множественных JOIN

4. Транзакции

PostgreSQL: встроенная поддержка ACID

BEGIN TRANSACTION;

INSERT INTO accounts (user_id, balance) VALUES (1, 1000);
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE user_id = 2;

-- Если ошибка, всё откатывается
COMMIT;  -- или ROLLBACK;

MongoDB: транзакции с версии 4.0

const session = db.getMongo().startSession();
session.startTransaction();

try {
    db.accounts.updateOne(
        { userId: 1 },
        { $inc: { balance: -100 } },
        { session }
    );
    db.accounts.updateOne(
        { userId: 2 },
        { $inc: { balance: 100 } },
        { session }
    );
    session.commitTransaction();
} catch (error) {
    session.abortTransaction();
    throw error;
}

5. Использование в Java

PostgreSQL с JDBC:

public class UserRepository {
    public User findById(Long id) {
        String query = "SELECT * FROM users WHERE id = ?";
        try (Connection conn = getConnection();
             PreparedStatement stmt = conn.prepareStatement(query)) {
            
            stmt.setLong(1, id);
            ResultSet rs = stmt.executeQuery();
            
            if (rs.next()) {
                return new User(
                    rs.getLong("id"),
                    rs.getString("name"),
                    rs.getString("email")
                );
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        return null;
    }
}

MongoDB с драйвером:

public class UserRepository {
    private MongoCollection<Document> usersCollection;
    
    public User findById(String id) {
        Document doc = usersCollection.find(
            Filters.eq("_id", new ObjectId(id))
        ).first();
        
        if (doc != null) {
            return new User(
                doc.getObjectId("_id").toString(),
                doc.getString("name"),
                doc.getString("email")
            );
        }
        return null;
    }
}

6. Сравнение таблица

ХарактеристикаPostgreSQLMongoDB
ТипРеляционная RDBMSДокументоориентированная NoSQL
СхемаФиксированнаяГибкая
Язык запросовSQLMongoDB Query Language
СвязиForeign Keys, JOINВстроенные документы, references
ТранзакцииACID по умолчаниюACID (v4.0+)
МасштабируемостьВертикальнаяГоризонтальная (sharding)
НормализацияРекомендуетсяМожет быть denormalization
Производительность чтенияХорошая (с индексами)Отличная (встроенные данные)
СложностьПростая схемаГибкость требует дисциплины
Open SourceДаДа (Community Edition)

7. Когда использовать

PostgreSQL для:

  • Структурированных данных с четкими отношениями
  • Финансовых систем, требующих строгой целостности данных
  • Приложений с сложными запросами и аналитикой
  • Малого-среднего объема данных с масштабированием по вертикали
  • Когда нужна надежность и стабильность
// Пример: система управления заказами
// Четкая структура: Users -> Orders -> Products
// Нужны JOIN и сложные отчеты
public class OrderService {
    // Сложный запрос с JOIN
    public List<OrderReport> getMonthlyReport(String month) {
        String sql = "SELECT u.name, COUNT(o.id) as order_count, " +
                     "SUM(o.amount) as total_amount " +
                     "FROM users u " +
                     "LEFT JOIN orders o ON u.id = o.user_id " +
                     "WHERE DATE_TRUNC(month, o.created_at) = ? " +
                     "GROUP BY u.id, u.name";
        // ...
    }
}

MongoDB для:

  • Неструктурированных или полуструктурированных данных
  • Приложений с быстро меняющейся схемой
  • Высоконагруженных систем с горизонтальным масштабированием
  • Когда нужна гибкость и скорость разработки
  • IoT, логирования, кеша
// Пример: система логирования событий
// Гибкая структура: разные типы событий
public class EventLogger {
    public void logEvent(Map<String, Object> eventData) {
        // Документы могут иметь разную структуру
        Document event = new Document(eventData)
            .append("timestamp", new Date())
            .append("type", eventData.get("type"));
        
        eventsCollection.insertOne(event);
    }
}

Заключение

Выбор между PostgreSQL и MongoDB зависит от:

  • Структура данных — четкая и связанная → PostgreSQL, гибкая → MongoDB
  • Масштаб — умеренный → PostgreSQL, огромный → MongoDB
  • Запросы — сложные JOIN → PostgreSQL, простые поиски → MongoDB
  • Требования — целостность данных → PostgreSQL, скорость → MongoDB

Многие крупные приложения используют оба подхода: PostgreSQL для основных данных, MongoDB для логов и кеша.