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

Что такое SQLAlchemy?

2.0 Middle🔥 201 комментариев
#SQL и базы данных

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

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

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

SQLAlchemy: ORM для работы с базами данных

SQLAlchemy — это один из самых мощных инструментов для работы с БД в Python. Для Data Scientist это фундаментальный навык, так как большинство данных хранится в реляционных БД.

Что такое SQLAlchemy

SQLAlchemy — это ORM (Object-Relational Mapper) и SQL toolkit для Python, который:

  1. Отображает таблицы БД на классы Python (ORM)
  2. Позволяет писать SQL через Python код (Query Builder)
  3. Управляет соединениями с БД (Connection Pooling)
  4. Абстрагирует разные СУБД (PostgreSQL, MySQL, SQLite, Oracle)

Архитектура

┌─────────────────────────────────────┐
│   Приложение (Python код)           │
├─────────────────────────────────────┤
│   SQLAlchemy ORM / Query Builder    │ ← Вы работаете с этим
├─────────────────────────────────────┤
│   SQLAlchemy Core (Dialects)        │ ← Абстракция БД
├─────────────────────────────────────┤
│   Python Database Drivers           │ ← psycopg2, pymysql
├─────────────────────────────────────┤
│   PostgreSQL / MySQL / SQLite       │ ← Реальная БД
└─────────────────────────────────────┘

Установка

pip install sqlalchemy
pip install psycopg2  # Для PostgreSQL
pip install pymysql   # Для MySQL

Основные концепции

1. Engine — соединение с БД

from sqlalchemy import create_engine

# PostgreSQL
engine = create_engine(
    'postgresql://user:password@localhost:5432/database_name'
)

# MySQL
engine = create_engine(
    'mysql+pymysql://user:password@localhost:3306/database_name'
)

# SQLite (локальный файл)
engine = create_engine('sqlite:///database.db')

# Проверка соединения
with engine.connect() as conn:
    result = conn.execute('SELECT 1')
    print('Connection successful!')

2. Session — управление транзакциями

from sqlalchemy.orm import sessionmaker

Session = sessionmaker(bind=engine)
session = Session()

# Используем session для всех операций
try:
    # Операции с БД
    session.commit()  # Сохраняем изменения
except Exception as e:
    session.rollback()  # Откатываем при ошибке
finally:
    session.close()  # Закрываем соединение

3. Declarative Base — ORM модели

from sqlalchemy import Column, Integer, String, Float, DateTime
from sqlalchemy.ext.declarative import declarative_base
from datetime import datetime

Base = declarative_base()

class User(Base):
    __tablename__ = 'users'
    
    id = Column(Integer, primary_key=True)
    username = Column(String(50), unique=True, nullable=False)
    email = Column(String(100), unique=True)
    age = Column(Integer)
    created_at = Column(DateTime, default=datetime.now)
    
    def __repr__(self):
        return f'User({self.username}, {self.email})'

class Purchase(Base):
    __tablename__ = 'purchases'
    
    id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey('users.id'))
    amount = Column(Float)
    created_at = Column(DateTime, default=datetime.now)

Практические примеры

Пример 1: CRUD операции

from sqlalchemy.orm import sessionmaker

Session = sessionmaker(bind=engine)
session = Session()

# CREATE (создание)
new_user = User(
    username='john_doe',
    email='john@example.com',
    age=30
)
session.add(new_user)
session.commit()
print(f'User created with id: {new_user.id}')

# READ (чтение)
user = session.query(User).filter_by(username='john_doe').first()
print(f'Found user: {user.username}, {user.email}')

# UPDATE (обновление)
user.age = 31
session.commit()
print(f'User age updated to {user.age}')

# DELETE (удаление)
session.delete(user)
session.commit()
print('User deleted')

session.close()

Пример 2: Сложные запросы (SQL эквивалент)

# SQL: SELECT * FROM users WHERE age > 25 ORDER BY username
users = session.query(User).filter(User.age > 25).order_by(User.username).all()

# SQL: SELECT username, email FROM users WHERE age BETWEEN 20 AND 30
users = session.query(User.username, User.email).filter(
    User.age.between(20, 30)
).all()

# SQL: SELECT COUNT(*) FROM users
count = session.query(User).count()

# SQL: SELECT * FROM users WHERE username LIKE 'john%'
users = session.query(User).filter(User.username.like('john%')).all()

# SQL: SELECT * FROM users WHERE age IN (25, 30, 35)
users = session.query(User).filter(User.age.in_([25, 30, 35])).all()

Пример 3: JOIN операции

from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship

# Определяем отношение
class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    username = Column(String(50))
    purchases = relationship('Purchase', back_populates='user')

class Purchase(Base):
    __tablename__ = 'purchases'
    id = Column(Integer, primary_key=True)
    user_id = Column(Integer, ForeignKey('users.id'))
    amount = Column(Float)
    user = relationship('User', back_populates='purchases')

# JOIN через relationship
user = session.query(User).filter_by(username='john').first()
print(f'User purchases: {user.purchases}')  # Автоматический JOIN

# JOIN через query
result = session.query(User.username, Purchase.amount).join(Purchase).all()

# LEFT JOIN
result = session.query(User).outerjoin(Purchase).all()

Пример 4: Для Data Science (загрузка в Pandas)

import pandas as pd
from sqlalchemy import create_engine

engine = create_engine('postgresql://user:pass@localhost/db')

# Способ 1: Прямое чтение в DataFrame
df = pd.read_sql(
    'SELECT * FROM users WHERE age > 25',
    engine
)
print(df.head())

# Способ 2: Через SQLAlchemy Query
from sqlalchemy.orm import Session

with Session(engine) as session:
    query = session.query(User).filter(User.age > 25)
    df = pd.read_sql(
        query.statement,  # Преобразуем Query в SQL statement
        engine
    )

# Способ 3: Полностью через Pandas
df = pd.read_sql_table('users', engine)  # Читает всю таблицу

# Сохранение обратно в БД
df.to_sql('processed_users', engine, if_exists='replace', index=False)

Пример 5: Полный ML pipeline с SQLAlchemy

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

engine = create_engine('postgresql://user:pass@localhost/ml_db')

# 1. Загрузка данных из БД
df = pd.read_sql(
    'SELECT * FROM training_data WHERE is_valid = true',
    engine
)
print(f'Loaded {len(df)} records')

# 2. Подготовка данных
X = df[['feature1', 'feature2', 'feature3']]
y = df['target']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

# 3. Обучение модели
model = LogisticRegression()
model.fit(X_train, y_train)
score = model.score(X_test, y_test)
print(f'Model accuracy: {score:.4f}')

# 4. Сохранение результатов в БД
Session = sessionmaker(bind=engine)
session = Session()

predictions_df = pd.DataFrame({
    'record_id': df.index,
    'prediction': model.predict(X),
    'probability': model.predict_proba(X)[:, 1]
})

predictions_df.to_sql('model_predictions', engine, if_exists='append', index=False)

session.close()

Преимущества SQLAlchemy

✓ Абстракция БД
  - Один код работает с PostgreSQL, MySQL, SQLite
  
✓ Безопасность
  - Защита от SQL injection через параметризованные запросы
  
✓ Удобство
  - Работаешь с объектами Python, а не со строками SQL
  
✓ Производительность
  - Connection pooling (переиспользование соединений)
  - Lazy loading и eager loading
  
✓ Гибкость
  - Можешь писать сырой SQL если нужно
  - Или использовать высокоуровневый ORM
  
✓ Тестируемость
  - Легко мокировать БД в тестах

Ограничения

✗ Кривая обучения
  - Требует понимания как ORM так и SQL
  
✗ Производительность на сложных запросах
  - Сгенерированный SQL может быть неоптимален
  
✗ Сложность отладки
  - Трудно отследить какой SQL генерируется

Отладка SQL

from sqlalchemy import event, pool
import logging

# Включаем логирование SQL
logging.basicConfig()
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)

engine = create_engine('postgresql://...', echo=True)  # Выведет все SQL

# Или смотрим сгенерированный SQL
query = session.query(User).filter(User.age > 25)
print(query)  # Выводит SQL statement
print(str(query.statement.compile(compile_kwargs={"literal_binds": True})))

Сравнение: SQL vs SQLAlchemy

# ══════════════════════════════════════════════════════════
# SQL (сырой SQL)
# ══════════════════════════════════════════════════════════
import sqlite3
conn = sqlite3.connect('db.sqlite')
cursor = conn.cursor()
cursor.execute(
    'SELECT * FROM users WHERE age > ? ORDER BY username',
    (25,)
)
results = cursor.fetchall()
conn.close()

# ══════════════════════════════════════════════════════════
# SQLAlchemy (ORM)
# ══════════════════════════════════════════════════════════
engine = create_engine('sqlite:///db.sqlite')
Session = sessionmaker(bind=engine)
session = Session()
results = session.query(User).filter(User.age > 25).order_by(User.username).all()
session.close()

# ══════════════════════════════════════════════════════════
# Преимущества SQLAlchemy:
# 1. Читаемость (объектно-ориентированный подход)
# 2. Безопасность (параметризованные запросы автоматически)
# 3. Переносимость (работает с разными СУБД)
# 4. Удобство (не нужно парсить кортежи)
# ══════════════════════════════════════════════════════════

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

✓ ИСПОЛЬЗУЙ:
  - Создание приложений с БД
  - Frequent read/write операции
  - Когда нужна абстракция от конкретной СУБД
  - Complex business logic с данными
  
✗ НЕ используй (используй сырой SQL):
  - One-off запросы для анализа
  - Очень сложные SQL запросы
  - Когда производительность критична
  - Быстрый прототип (просто используй Pandas)

Для Data Scientist: рекомендуемый подход

# 1. Для изучения данных → используй Pandas
df = pd.read_sql('SELECT * FROM table LIMIT 100', engine)

# 2. Для production pipeline → используй SQLAlchemy ORM
from sqlalchemy.orm import Session
with Session(engine) as session:
    results = session.query(Model).filter(...).all()

# 3. Для сложных аналитических запросов → сырой SQL через Pandas
df = pd.read_sql('SELECT ... FROM ... WHERE ...', engine)

# 4. Для сохранения результатов → ORM или to_sql
results_df.to_sql('results_table', engine, if_exists='append')

Заключение

SQLAlchemy — это:

  • Essential инструмент для work с БД в Python
  • Мощный ORM для абстракции таблиц
  • Flexible toolkit для SQL queries
  • Essential для production ML систем

Для Data Scientist: изучите основы SQLAlchemy для работы с production системами, но используйте Pandas для быстрого анализа данных.