← Назад к вопросам
При работе с PostgreSQL использовал ORM или писал сырые SQL-запросы
1.7 Middle🔥 231 комментариев
#Python Core#Базы данных (SQL)
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
При работе с PostgreSQL использовал ORM или писал сырые SQL-запросы?
Использую оба подхода, в зависимости от задачи. Нет универсального решения.
ORM (Object-Relational Mapping)
Использую ORM для:
- CRUD операций (Create, Read, Update, Delete)
- Простых и средних запросов
- Быстрой разработки
- Защиты от SQL-инъекций
- Связей между таблицами
Популярные Python ORM:
- SQLAlchemy (самый мощный)
- Django ORM (встроен в Django)
- Tortoise ORM (асинхронный)
Пример с SQLAlchemy:
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
class User:
__tablename__ = "users"
id = Column(Integer, primary_key=True)
name = Column(String)
email = Column(String)
engine = create_engine("postgresql://user:pass@localhost/db")
Session = sessionmaker(bind=engine)
session = Session()
# CREATE
user = User(name="Alice", email="alice@example.com")
session.add(user)
session.commit()
# READ
users = session.query(User).filter(User.name == "Alice").all()
# UPDATE
user = session.query(User).filter(User.id == 1).first()
user.email = "new@example.com"
session.commit()
# DELETE
session.query(User).filter(User.id == 1).delete()
session.commit()
Сырые SQL-запросы
Пишу сырые SQL для:
- Сложных запросов (CTE, window functions, группировки)
- Оптимизации производительности
- PostgreSQL-специфичных функций
- Аналитических запросов
Пример с SQLAlchemy:
from sqlalchemy import text
query = text("""
SELECT
users.id,
users.name,
COUNT(orders.id) as order_count
FROM users
LEFT JOIN orders ON users.id = orders.user_id
WHERE users.created_at > :date
GROUP BY users.id
HAVING COUNT(orders.id) > :min_orders
ORDER BY order_count DESC
""")
result = session.execute(query, {"date": "2024-01-01", "min_orders": 5})
for row in result:
print(row)
Сравнение
| Критерий | ORM | Raw SQL |
|---|---|---|
| Скорость разработки | Быстро | Медленнее |
| SQL-инъекции | Защищено | Нужно следить |
| Производительность | Может быть медленнее | Оптимальнее |
| Сложные запросы | Затруднительно | Естественно |
| Читаемость | Хорошо | Зависит |
Мой гибридный подход
Начинаю с ORM, переходу на SQL если нужна оптимизация.
class UserRepository:
def __init__(self, session):
self.session = session
# Простой запрос — ORM
def get_by_id(self, user_id: int):
return self.session.query(User).filter(User.id == user_id).first()
# Средний запрос — ORM
def get_active_users(self):
return self.session.query(User).filter(
(User.is_active == True) & (User.verified == True)
).all()
# Сложный аналитический запрос — сырой SQL
def get_statistics(self, start_date, end_date):
query = text("""
SELECT
DATE_TRUNC("day", created_at) as date,
COUNT(*) as new_users,
COUNT(CASE WHEN verified = true THEN 1 END) as verified
FROM users
WHERE created_at BETWEEN :start_date AND :end_date
GROUP BY DATE_TRUNC("day", created_at)
ORDER BY date
""")
return self.session.execute(query, {
"start_date": start_date,
"end_date": end_date
}).fetchall()
Лучшие практики
1. Всегда используй параметры, не строковую интерполяцию
# Правильно
query = text("SELECT * FROM users WHERE id = :user_id")
result = session.execute(query, {"user_id": user_id})
# Неправильно
result = session.execute(f"SELECT * FROM users WHERE id = {user_id}")
2. Профилируй запросы в production
Включи логирование SQL в development:
import logging
logging.basicConfig()
logging.getLogger("sqlalchemy.engine").setLevel(logging.INFO)
3. Используй индексы для сложных запросов
CREATE INDEX idx_users_created_at ON users(created_at);
CREATE INDEX idx_orders_user_id ON orders(user_id);
Распределение подходов
Мой опыт показывает:
- 70% ORM для обычных CRUD операций
- 30% Raw SQL для сложных аналитических запросов
- Всегда используй параметризованные запросы
- Оптимизируй только когда есть проблемы с производительностью
- Документируй сложные SQL запросы
Заключение
Выбираю инструмент в зависимости от задачи. ORM удобен для типовых операций, SQL дает контроль и производительность для сложных случаев.