【问题标题】:Identify Django queryset from SQL logs从 SQL 日志中识别 Django 查询集
【发布时间】:2019-12-18 21:14:15
【问题描述】:

我使用 Django 1.8.17(我知道它不再那么年轻了)。 我在 PostGres 上记录了慢速请求超过一分钟。

我很难找到日志中列出的 SQL 查询所属的查询集。

是否有一个标识符可以添加到查询集中以在日志中查找关联的 SQL 查询或轻松识别它的技巧?

这是一个几乎无法识别的常见查询集示例,因为我有几个相似的查询集。

Queryset:
Video.objects.filter(status='online').order_by('created')

LOGs:
duration: 1056.540 ms  statement: SELECT "video"."id", "video"."title", 
"video"."description", "video"."duration", "video"."html_description", 
"video"."niche_id", "video"."owner_id", "video"."views", 
"video"."rating" FROM "video" WHERE "video"."status" = 'online' 
ORDER BY "video"."created"

Desired LOGs:
duration: 1056.540 ms  statement: SELECT "video"."id", "video"."title", 
"video"."description", "video"."duration", "video"."html_description", 
"video"."niche_id", "video"."owner_id", "video"."views", 
"video"."rating" FROM "video" WHERE "video"."status" = 'online' 
ORDER BY "video"."created" (ID=555)

【问题讨论】:

  • 不确定我是否理解,上面的示例显示了属于日志的查询集。 “识别查询集”是什么意思?
  • 我知道情况正好相反,但是如果您为所有可疑查询集打印查询集的 query(例如作为调试日志记录),您应该能够匹配它们。跨度>
  • @dirkgroten 这是一个例子。事实上,我不知道它是哪个 Queryset。我只是展示了基本的查询集是多么的难以与 SQL LOG 关联
  • @dirkgroten。打印查询即将在很多查询集上打印。在每个之后添加打印,然后将其删除,这是一项艰巨的任务。我想知道它通常是如何制作的。如果我没有找到任何参数来实现我的目标,我会以这个结束,但我想肯定有人在我之前考虑过这个。
  • 在开发中,您可以使用 Django-debug-toolbar,它会显示您的所有 SQL 查询以及触发它的代码行。

标签: sql django postgresql logging django-queryset


【解决方案1】:

添加中间件以在查询需要很长时间时记录警告:

class LongQueryLogMiddleware(object):
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        for q in connection.queries:
            if float(q['time']) >= settings.LONG_QUERY_TIME_SEC:
                logger.warning("Found long query (%s sec): %s", q['time'], q['sql'])
        return response

我用所有代码制作了一个小的gist。很抱歉缩进,GitHub 一直在删除缩进。

在上面的代码中,我只记录查询,但您可以添加request 信息,这将帮助您确定查询的来源。

【讨论】:

  • 这会使用 log_min_duration_statement 记录我在 Postgresl 日志中已有的 SQL。我需要的是在 Queryset 中“标记” SQL 查询,以识别哪个 Queryset 对应于 SQL 日志。顺便说一句,这个中间件不适用于 Django 1.8,它是新的中间件方案,我必须适应它。
  • 但是,如果您还将请求信息添加到日志消息中,您将知道查询集被触发的位置,例如在哪个视图中。这样就可以很容易地在您的代码中找出它是哪个查询集。
【解决方案2】:

我不了解 Django,所以我可能不正确,但是我从一个运行 RDS 的人那里听到了一个简单的技巧:

在您的查询中添加一个标识符作为注释。

因此,在查询中包含 UUID、ID、标签等

--作为评论

这将流向日志。这是一种将 Postgres 日志条目绑定到特定方法/脚本的简单方法,听起来它需要一些适应才能在您的情况下有用。 (如果这个想法完全适用的话。)

【讨论】:

  • 这就是重点!但遗憾的是 Django 不支持 cmets。我认为它不会实施,因为它可能不是解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-19
  • 2017-11-14
  • 2012-07-16
  • 2012-06-01
  • 2019-03-19
  • 2013-06-11
  • 1970-01-01
相关资源
最近更新 更多