加速嵌套的 Django ORM 查询
Speeding up nested Django ORM queries
我在我的 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
模型。
使用 Session 库,我需要找到我的应用程序中当前没有条目的用户数量 table(及其对应的 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
我的会话 table 包含 1.7M 行,而用户 table 包含 408K 行。上面的代码花费了异常大量的处理时间(即几分钟),并最终在生产中给我一个 500 错误(在开发中的有限数据集上正常工作)。
在解决问题之前,我觉得我还应该优化查询以获得结果的成本更低。
您认为我的代码需要哪些明显的优化?我知道我可以通过从 total_users
中减去 logged_in_users
的数量来找到 logged_out_users
的数量。但是如何获取他们所有的 ID?
[更新]:在评论中进行了一些讨论后,问题询问了有关检索(和计数)已注销 User
的 id
的问题]s(即根本没有 Session
table 条目的用户)。
所以:
# 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()
这个怎么样:
# Fetch all user_id values from the Session table where the user ForeignKey has
# no value (thus, it's null)
null_user_ids = Session.objects.filter(user__isnull=True).values_list('user__id', flat=True)
# Count the null users
no_of_users = null_user_ids.count()
我在我的 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
模型。
使用 Session 库,我需要找到我的应用程序中当前没有条目的用户数量 table(及其对应的 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
我的会话 table 包含 1.7M 行,而用户 table 包含 408K 行。上面的代码花费了异常大量的处理时间(即几分钟),并最终在生产中给我一个 500 错误(在开发中的有限数据集上正常工作)。
在解决问题之前,我觉得我还应该优化查询以获得结果的成本更低。
您认为我的代码需要哪些明显的优化?我知道我可以通过从 total_users
中减去 logged_in_users
的数量来找到 logged_out_users
的数量。但是如何获取他们所有的 ID?
[更新]:在评论中进行了一些讨论后,问题询问了有关检索(和计数)已注销 User
的 id
的问题]s(即根本没有 Session
table 条目的用户)。
所以:
# 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()
这个怎么样:
# Fetch all user_id values from the Session table where the user ForeignKey has
# no value (thus, it's null)
null_user_ids = Session.objects.filter(user__isnull=True).values_list('user__id', flat=True)
# Count the null users
no_of_users = null_user_ids.count()