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 添加查询 搜索小图标显示