我可能在标题中问了错误的问题。这是事实:

我的客户服务人员在我们基于Django网站的管理界面上进行客户查找时,一直抱怨响应时间缓慢。

我们正在使用Postgres 8.4.6。我开始记录缓慢的查询,发现了这个罪魁祸首:

SELECT COUNT(*) FROM "auth_user" WHERE UPPER("auth_user"."email"::text) LIKE UPPER(E'%deyk%')

此查询需要超过32秒的时间运行。这是解释提供的查询计划:

QUERY PLAN
Aggregate  (cost=205171.71..205171.72 rows=1 width=0)
  ->  Seq Scan on auth_user  (cost=0.00..205166.46 rows=2096 width=0)
        Filter: (upper((email)::text) ~~ '%DEYK%'::text)

因为这是Django Orm生成的查询,该查询是由Django Admin应用程序生成的Django Queryset生成的,所以我对查询本身没有任何控制权。索引似乎是逻辑解决方案。我尝试创建一个索引来加快这一速度,但没有区别:

CREATE INDEX auth_user_email_upper ON auth_user USING btree (upper(email::text))

我究竟做错了什么?我该如何加快此查询?

有帮助吗?

解决方案

没有索引支持 LIKE / ILIKEPostgreSQL 8.4 - 除了 左锚搜索词.

自从 Postgresql 9.1 附加模块 pg_trgm 为杜松子酒和要点的三格指数提供操作员课程 LIKE / ILIKE 或正则表达式(操作员 ~ 和朋友)。每个数据库安装一次:

CREATE EXTENSION pg_trgm;

示例杜松子酒索引:

CREATE INDEX tbl_col_gin_trgm_idx ON tbl USING gin (col gin_trgm_ops);

有关的:

其他提示

该索引在比赛开始时的“%”是没有帮助的 - btree索引只能匹配前缀,而查询开始时的通配符意味着没有固定的前缀可以寻找。

这就是为什么它正在进行表扫描并依次与查询字符串相匹配的原因。

您可能需要查看使用全文索引和文本匹配运算符,而不是目前使用类似的子字符串搜索。您可以在文档中找到有关全文搜索的更多信息:

http://www.postgresql.org/docs/8.4/static/textsearch-intro.html

实际上,我从该页面上注意到,显然从来没有使用过索引,这对我来说似乎很奇怪,因为它应该能够使用BTREE索引来解决非Wildcard前缀。一些快速的测试表明,文档可能是正确的,但是在这种情况下,您在使用更喜欢解决查询时无需提供帮助。

许可以下: CC-BY-SA归因
不隶属于 dba.stackexchange
scroll top