Django Admin 搜索查询未命中 Postgres 索引

Posted

技术标签:

【中文标题】Django Admin 搜索查询未命中 Postgres 索引【英文标题】:Django Admin search query not hitting Postgres index 【发布时间】:2012-12-26 09:53:12 【问题描述】:

我在 Postgres(所有本地主机)中使用 GIN 索引进行全文搜索,当我编写自己的查询并在 psql 中运行它时,我得到了很好的响应时间,EXPLAIN ANALYZE 报告索引命中(woohoo),但是当通过 Django Admin 搜索框使用相同的搜索词进行查询时,不会扫描索引,并且查询需要永远完成。

我的索引是通过fully-awesome pg_trgm Postgres extension创建的:

CREATE INDEX name_gin ON entity USING gin (name gin_trgm_ops);

此查询命中索引并花费了惊人的 84 毫秒 来搜索 90 万条全文记录:

SELECT COUNT(*) 
FROM entity 
WHERE name LIKE UPPER('%dubteeeff%') 
 AND name LIKE UPPER('%django%');

由 Django 管理界面创建的完全相同的查询需要 938 毫秒

SELECT COUNT(*) 
FROM entity 
WHERE UPPER("entity"."name"::text) LIKE UPPER('%dubteeeff%') 
  and UPPER("entity"."name"::text) LIKE UPPER('%django%');`

唯一的区别似乎是引用列的方式——我对 Django 和 Postgres 还很陌生——是否有一些 Postgres 配置设置或 Django 管理 QuerySet-something,或者我可以覆盖或修改的 RawQuery加快速度?我不希望我的管理页面充其量是缓慢的,最坏的情况是,将网站的其余部分拖下来。

提前致谢。

【问题讨论】:

不同之处在于您的查询中引用了该列。在 djange Query 中使用了一个表达式upper(name),它没有被索引。 Araqnid 是对的,您可能需要在upper(name) 上而不是“只是”name 上的索引。或者教 django 不应用 upper 函数(也许告诉它使查询不区分大小写) 【参考方案1】:

看起来您需要在 entity(upper(name)) 而不是 entity(name) 上添加索引,以便 Django 生成不区分大小写的搜索。

【讨论】:

谢谢——我不敢相信我没有注意到这一点。生成大写索引,它就像一个魅力。【参考方案2】:

这可能是 COUNT(*) 在 Postgres 中运行缓慢的问题吗?您可能需要检查修改查询以返回估计值而不是精确计数,因为这是 Postgres 的一个已知问题。

【讨论】:

谢谢,但我已经做到了—— COUNT(*) 本身非常快。另外,如果这是问题所在,为什么查询会很快? 啊——是的。看起来这个问题与 Postgres 没有以与 name 相同的方式解释 UPPER("entity"."name"::text) 有关。不知道为什么会这样,或者如何阻止 Django 这样做。祝你好运! 如果你使用i*关键字过滤不区分大小写,Django将在SQL中使用UPPER().filter(name__istartswith=...)icontains

以上是关于Django Admin 搜索查询未命中 Postgres 索引的主要内容,如果未能解决你的问题,请参考以下文章

django admin TabularInline raw_id_fields 添加查询 搜索小图标显示

使用jquery post时未调用django formview中的post函数

重复一个相关查询时,Django,多个数据库命中

ES实战Term查询未命中问题

ES实战Term查询未命中问题

dgango中admin下添加搜索功能