加速嵌套的Django ORM查询

时间:2017-03-21 16:37:12

标签: django django-models django-orm

我在Django项目中使用了方便的Django sessions library。这允许我通过ORM查询处理Session对象。

我可以为每个Session对象访问的属性是:

    Column     |           Type           | Modifiers 
---------------+--------------------------+-----------
 session_key   | character varying(40)    | not null
 session_data  | text                     | not null
 expire_date   | timestamp with time zone | not null
 user_id       | integer                  | 
 user_agent    | character varying(200)   | not null
 last_activity | timestamp with time zone | not null
 ip            | inet                     | not null

user_id来自Django User模型。

使用会话库,我需要找到我的应用中当前在会话表中没有条目的用户数(以及相应的IDs)。

我通过以下方式尝试了它:

logged_in_users = set(Session.objects.values_list('user_id',flat=True))
logged_in_users = [user_pk for user_pk in logged_in_users if user_pk is not None]
logged_out_users = set(User.objects.exclude(id__in=logged_in_users).values_list('id',flat=True))
num_logged_out = len(logged_out_users) #passed to template to display

我的会话表包含 1.7M 行,而用户表包含 408K 行。上面的代码占用了异常大量的处理时间(即几分钟),最终在生产中产生了500错误(在开发中的有限数据集上正常工作)。

在解决问题之前,我觉得我也应该优化查询以降低成本。

您觉得我的代码需要哪些明显的优化?我知道我可以通过从logged_out_users中减去logged_in_users的数量来找到total_users的数量。但是如何获取所有ID?

1 个答案:

答案 0 :(得分:1)

[更新] :在评论中进行了一些讨论之后,问题是检索(并计算)已注销的id的{​​{1}}(即用户)在User表中根本没有条目。

所以:

Session

这个怎么样:

# Get a (flat) list of user ids where the user entry in not null
logged_in_users = Session.objects.filter(user__isnull=False).values_list('user__id', flat=True).distinct()

# Get a (flat) list of user ids excluding the previous logged ones (thus, this list will contain the logged out users)
logged_out_users = User.objects.exclude(id__in=logged_in_users).values_list('id', flat=True).distinct()

# Count the logged out users
logged_out_users_count = logged_out_users.count()