Django是一个很好的python框架,他的orm很好用,允许开发者使用Python代码来操作数据库,而无需直接编写复杂的SQL语句,极大地简化了数据库交互的流程。

用Django 的orm查询很简单,下面这两种写法也比较常见。

xxx = MyModel.objects.get(id=1)

xxx = MyModel.objects.filter(id=1).first()

不过如果你喜欢直接删除表里的记录,而不是用什么额外的字段来软删除的话,上面这两个写法对于已经删除的记录,或者id不存在的记录都需要额外进行判断。

try:
    xxx = MyModel.objects.get(id=1)
except MyModel.DoesNotExist:
    xxx

xxx = MyModel.objects.filter(id=1).first()
if xxx:
    do_sth()

这两种写法都不错,不过如果用filter(xxx=xxx).first() 方法的话,生成的sql默认是会有一个排序的,而排序也是会要一点时间的。

我们可以在settings.py里面设置一下,开启orm查询时的sql日志:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'level': 'DEBUG',
            'propagate': True,
        },
    },
}

添加设置后,等待服务重启,或者直接python manager.py shell开启命令行模式来测试。

从上面两个sql可以看到filter first 方法多了一个id排序。

性能分析

  • 索引的使用

    • 因为id 是主键,两个查询都会直接通过索引定位到目标记录,性能几乎相同。

    • 如果没有索引,数据库会进行全表扫描,性能会较差,但两个查询的扫描成本是相同的。

  • 排序的影响

    • 第一个查询中包含了 ORDER BY id ASC,但由于 id 是唯一的,排序操作并不会改变结果。

    • 大多数数据库引擎会优化这种情况,直接忽略排序操作,因此不会增加额外的性能开销。

总结

建议在需要检索唯一对象时,优先使用 .get(),而不是 .first(),使用 .first() 会引入不必要的 ORDER BY,可能会影响性能。不过,如果查询字段上有索引,这个排序的性能开销通常可以忽略不计。

欢迎大家关注我的公众号,追更更轻松~

Snipaste_2024-12-07_11-05-00.png