Python SQLAlchemy 排序性能优化:从负号到 desc() 函数

键盘旁的猫
键盘旁的猫
发布时间:2026-10-10| 2人浏览过
原创

在 Python 的 SQLAlchemy 框架中,使用负号(如 -Model.field)进行降序排序可能导致严重的性能问题。本文深入分析这一常见陷阱,对比使用负号与调用 .desc() 方法的执行效率,并展示如何通过正确的排序方式提升查询速度。此外,文章还提供了一个利用随机数与最大 ID 结合的高效随机数据抽取方案,帮助开发者避免全表扫描,实现高性能的数据处理。

SQLAlchemy 排序中的性能陷阱

SQLAlchemy 是 Python 生态中广泛使用的 ORM(对象关系映射)框架。它建立在数据库 API 之上,通过关系对象映射将 Python 对象转换为 SQL 语句,并利用数据 API 执行 SQL 并获取结果。这种抽象极大地简化了数据库操作,但在某些细节处理上,如果不加注意,可能会引入性能瓶颈。

一个典型的例子发生在数据排序上。许多开发者习惯使用 Python 的负号操作符(如 -UserVideo.vid)来表示降序排列。虽然这在语法上是合法的,并且 SQLAlchemy 能够将其转换为对应的 SQL 语句,但这种写法在底层执行时往往无法充分利用数据库的索引优势,导致查询速度显著下降。

优化方案:使用 desc() 函数

为了解决上述性能问题,推荐的做法是显式调用 SQLAlchemy 提供的 desc() 函数。通过对比两种实现方式,我们可以清晰地看到性能差异。

低效写法:使用负号

以下是使用负号进行排序的代码示例。这种写法虽然简洁,但在数据量较大时,查询耗时可能非常可观。

query = db_session.query(UserVideo.vid,
         UserVideo.uid,
         UserVideo.v_width,
         UserVideo.v_height,
         UserVideo.create_time,
         UserVideo.cover,
         UserVideo.source_url,
         UserVideo.v_type,
         UserVideo.category,
         User.username,
         User.sex,
         UserExtraInfo.avatar,
         UserExtraInfo.watermark)
  query = query.filter(UserVideo.status == 1,
        User.uid == UserVideo.uid,
        UserExtraInfo.uid == UserVideo.uid) 
  query = query.filter(UserVideo.status == 1)
  query = query.order_by(-UserVideo.vid)
  query = query.limit(20).all()

高效写法:使用 desc()

将排序逻辑改为显式调用 .desc() 方法后,数据库优化器通常能更有效地利用索引进行排序,从而大幅提升查询速度。实测表明,这种优化可使查询速度提高约 10 倍。

query = db_session.query(UserVideo.vid,
         UserVideo.uid,
         UserVideo.v_width,
         UserVideo.v_height,
         UserVideo.create_time,
         UserVideo.cover,
         UserVideo.source_url,
         UserVideo.v_type,
         UserVideo.category,
         User.username,
         User.sex,
         UserExtraInfo.avatar,
         UserExtraInfo.watermark)
  query = query.filter(UserVideo.status == 1,
        User.uid == UserVideo.uid,
        UserExtraInfo.uid == UserVideo.uid) # .order_by(UserVideo.vid.desc()).limit(20).all()
  query = query.filter(UserVideo.status == 1)
  query = query.order_by(UserVideo.vid.desc())
  query = query.limit(20).all()

高性能随机数据抽取技巧

除了排序优化,在实际业务中,我们经常需要从数据库中随机抽取若干条数据。传统的 ORDER BY RAND() 或类似全表扫描的方法在数据量大时效率极低。下面提供一个基于 SQLAlchemy 的高性能随机抽取方案。

该方案的核心思路是:先生成一个介于 0 和最大 ID 之间的随机数,然后筛选出 ID 大于该随机数的记录。这种方法避免了全表排序,显著提升了随机取数的效率。

query = db_session.query(UserVideo.vid,
          UserVideo.uid,
          UserVideo.v_width,
          UserVideo.v_height,
          UserVideo.create_time,
          UserVideo.cover,
          UserVideo.source_url,
          UserVideo.v_type,
          UserVideo.category,
          User.username,
          User.sex,
          UserExtraInfo.avatar,
          UserExtraInfo.watermark)
   query = query.filter(UserVideo.status == 1, User.uid == UserVideo.uid, UserExtraInfo.uid == UserVideo.uid)
rvid = db_session.query(func.round(random.random() * func.max(UserVideo.vid)).label('rvid')).subquery()
query = query.filter(UserVideo.category == category)
query_tail = query
query_tail = query_tail.join(rvid, UserVideo.vid > rvid.c.rvid).limit(20).all()

在上述代码中,func.max(UserVideo.vid) 用于获取当前表中的最大 ID,random.random() 生成 0 到 1 之间的随机数,两者相乘并取整后得到随机阈值 rvid。随后,通过子查询 rvid 与主查询进行连接,筛选出 UserVideo.vid > rvid.c.rvid 的记录,并限制返回 20 条结果。这种方法在保证随机性的同时,极大地提高了查询效率。

总结

在 Python 的 SQLAlchemy 开发中,细节决定性能。避免使用负号进行排序,转而使用 desc() 函数,可以显著提升查询速度。同时,掌握高性能随机数据抽取的技巧,能够帮助我们在处理大规模数据时保持系统的响应能力。希望本文的内容能对您的开发工作有所帮助。

以上就是浅析python中SQLAlchemy排序的一个坑的详细内容,更多关于Python SQLAlchemy性能优化的资料请关注本站其它相关文章!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。