我有一个监视网站事件的应用程序,部分用户界面显示给定时间段内每个网站的事件计数。这些模型如下所示:
[
{
"name" : "test1",
"city" : "London",
"applications" : [
{
"app" : "stackoverflow",
"app_city" : "New York",
"app_hobies" : [ {
"hobby" : "football",
"hobby_time" : "daily"}
}]
}]
这些网站每天产生数千个事件,因此[
{
"_id" : ObjectId("12121"),
"name" : "test1",
"city" : "London",
"applications" : [
{
"_id" : ObjectId("4343"),
"app" : "stackoverflow",
"app_city" : "New York",
"app_hobies" : [ {
"_id" : ObjectId("21322"),
"hobby" : "football",
"hobby_time" : "daily"}
}]
}]
表与其他表相比非常大。这是我要生成的查询的样子:
class Website(models.Model):
name = models.CharField(max_length=64)
url = models.TextField()
class Event(models.Model):
website = models.ForeignKey(Website, related_name="events")
created_at = models.DateTimeField(default=timezone.now)
ip_address = models.CharField(max_length=64)
status = models.CharField(max_length=16)
message = models.CharField(max_length=128)
就像我之前提到的,Event
表中包含数百万行。对于少数网站,此查询不会花费太长时间。但是,当有100个或更多的网站时,它会花费相当长的时间。我已经进行了一些分析,数据库(内部)正在查询每个网站的计数。因此,如果我有100个网站,则数据库将进行100个查询以生成计数(仍然有一个查询来自Django,但Postgres内部正在进行这100个子查询)。
我想做的是预取这些计数,因为当我运行以下原始SQL时,它实际上非常快:
eargs = {
"website": OuterRef("pk"),
"created_at__gte": some_start_time,
"created_at__lt": some_end_time
}
events = Event.objects.filter(**eargs).values("website")
events_count = events.annotate(c=Count("*").values("c")[:1]
websites = Website.objects.annotate(events=Coalesce(Subquery(events_count,
output_field=IntegerField()), 0)
有没有可能预取该查询并仍在QuerySet中使用结果的方法?还是我把这一切弄错了?似乎这是很平常的事,我很难把头放在如何加快速度上。