ORM 与原生 SQL 的选择

2026-06-22 · 6 阅读 · 379字
GoPython数据库

ORM 与原生 SQL 的选择

ORM 的优势

提高开发效率

ORM 将数据库表映射为对象,开发者可以用熟悉的编程语言操作数据库,无需编写 SQL:

# ORM 方式
users = User.query.filter_by(status='active').order_by(User.created_at.desc()).all()

# 原生 SQL
cursor.execute("SELECT * FROM users WHERE status = %s ORDER BY created_at DESC", ('active',))
users = cursor.fetchall()

防止 SQL 注入

ORM 框架自动处理参数转义和预处理语句,天然免疫 SQL 注入。

数据库迁移

ORM 通常提供迁移工具,方便管理数据库 Schema 变更:

# Alembic migration example
def upgrade():
    op.create_table('users',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('name', sa.String(length=255), nullable=False),
        sa.Column('email', sa.String(length=255), nullable=False),
        sa.PrimaryKeyConstraint('id'),
        sa.UniqueConstraint('email')
    )

模型关系管理

ORM 提供了直观的关系管理方式:

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    posts = relationship('Post', back_populates='author')

class Post(Base):
    __tablename__ = 'posts'
    id = Column(Integer, primary_key=True)
    author_id = Column(ForeignKey('users.id'))
    author = relationship('User', back_populates='posts')

# 使用
user = session.get(User, 1)
for post in user.posts:  # 自动 JOIN
    print(post.title)

原生 SQL 的优势

性能可控

原生 SQL 可以精确控制查询计划,避免 ORM 生成的低效查询:

-- ORM 可能生成 N+1 条查询
SELECT * FROM users WHERE id = 1;
SELECT * FROM posts WHERE author_id = 1;

-- 原生 SQL 一条搞定
SELECT u.*, p.* FROM users u
LEFT JOIN posts p ON p.author_id = u.id
WHERE u.id = 1;

复杂查询

ORM 在复杂查询面前力不从心:

-- 窗口函数 + 子查询
SELECT
    department,
    employee_name,
    salary,
    RANK() OVER (PARTITION BY department ORDER BY salary DESC) as rank
FROM employees
WHERE (department, salary) IN (
    SELECT department, MAX(salary)
    FROM employees
    GROUP BY department
);

精细的索引控制

原生 SQL 可以显式使用索引提示(如 PostgreSQL 的 SET LOCAL enable_seqscan = off)或撰写特定于数据库的查询。

选型决策框架

选择 ORM 的场景

  • CRUD 密集型应用,查询逻辑相对简单
  • 团队对 SQL 不熟悉
  • 需要快速迭代,开发速度优先
  • 需要数据库无关性(如同时支持 SQLite 和 PostgreSQL)

选择原生 SQL 的场景

  • 复杂报表和数据分析
  • 高并发场景,需要精确控制每个查询
  • 大量数据批量操作
  • 使用数据库特有特性(全文检索、GIS、JSONB 等)

混合使用(推荐)

实际项目中最合理的做法是两者结合:

# 80% 简单查询用 ORM
users = User.query.filter_by(status='active').all()

# 20% 复杂查询用原生 SQL
result = db.session.execute("""
    SELECT
        u.id,
        u.name,
        COUNT(o.id) as order_count,
        SUM(o.amount) as total_spent
    FROM users u
    LEFT JOIN orders o ON o.user_id = u.id
    WHERE u.created_at >= :since
    GROUP BY u.id
    HAVING COUNT(o.id) > :min_orders
    ORDER BY total_spent DESC
    LIMIT :limit
""", {'since': since, 'min_orders': 5, 'limit': 100}).fetchall()

常见 ORM 对比

ORM 语言 特点
SQLAlchemy Python 功能强大,支持复杂查询
GORM Go 使用广泛,约定优于配置
Prisma TypeScript 类型安全,Schema 驱动
Entity Framework C# LINQ 集成,微软生态
Diesel Rust 类型安全,编译期检查