【问题标题】:Quickest way to get element by index in QuerySet在 QuerySet 中按索引获取元素的最快方法
【发布时间】:2018-02-12 18:11:12
【问题描述】:

考虑到大约有 500 万个对象,我正在尝试在 Django 中为我的系统创建高效的搜索功能。

这就是我设置查询的方式:

objects_found = (Model.objects.extra(where=["CHAR_LENGTH(attribute) > 300"])).filter(attribute__trigram_similar=query)

我知道这个 QuerySet 尚未完全评估,而这正是我不想要的。

例如,要像这样完成评估设置的 QuerySet:

list(objects_found)

大约需要 60 秒。

如果我想以经典方式获取设置的 QuerySet 的第一项,仍然需要大约 60 秒,因为查询是针对所有对象启动的:

objects_found[0]

但是如果我使用像first()这样的方法:

objects_found.first()

大约需要 9 秒,这意味着不评估完整的 QuerySet。


假设objects_found 有500 个对象。如果我需要做这样的事情怎么办:

objects_found[40]

或者这个:

objects_found[:15]

以一种省时的方式?

p.s 切片确实会在 db 级别创建偏移选项,但由于某种原因在时间上没有差异。

因此,代码不会搜索所有 500 个对象,而是仅搜索 4015 对象。

在 Django QuerySet 中是否有任何实现可以做到这一点?

【问题讨论】:

    标签: django django-queryset


    【解决方案1】:

    您可以按照limiting querysets 文档中的说明将查询切出来限制查询

    objects_found = (Model.objects.extra(where=["CHAR_LENGTH(attribute) > 300"])).filter(attribute__trigram_similar=query)[:15]
    

    您的查询在数据库上非常困难,而且 CHAR_LENGTH 之类的函数对于运行每个查询运行时并不是那么理想,因此您可能可以将长度提取到整数行而不是执行 CHAR_LENGTH。

    关于三元组,您可以创建索引 https://www.postgresql.org/docs/9.1/static/pgtrgm.html#AEN143603

    此外,如果您更喜欢通过 Django 创建索引,以下资源可能会很有用 https://vxlabs.com/2018/01/31/creating-a-django-migration-for-a-gist-gin-index-with-a-special-index-operator/

    【讨论】:

    • 由于某种原因这不起作用,加载完整列表所需的时间一样多。 (顺便说一句,我没有否决你的答案)。
    • @ShellRox 预计后续会花费很长时间,因为您可能没有设置索引,您应该尝试使用三元索引优化您的查询,并且您可以将字符长度转换为字段以获得更快结果
    • 感谢您的建议!你知道我如何利用三元索引吗?我在任何地方都找不到它。 docs.djangoproject.com/en/2.0/ref/contrib/postgres/indexes
    • 以下没有官方迁移设置,但如果您不喜欢手动设置索引,我附上了似乎很有用的资源
    • 对不起,我缺乏数据库方面的经验。这个索引对每个数据库都是永久的吗?例如,它会通过 db 命令对它们进行永久排序吗?或者它们应该在每个查询中执行
    猜你喜欢
    • 2018-07-01
    • 1970-01-01
    • 2013-08-29
    • 2012-04-10
    • 2020-02-26
    • 2013-06-02
    • 2016-01-03
    • 2014-11-30
    • 1970-01-01
    相关资源
    最近更新 更多