🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
> 问题现象:使用pgsql过程中,业务上常用的模糊查询sql语句在执行过程中不经过索引 从下图可以看出,like模糊查询在执行过程中 Seq Scan on alerts 是顺序扫描全表 ![](https://img.kancloud.cn/a4/3b/a43b405c03a4b76f2d26affe30dafdb9_726x573.png) **原因分析:**        pgsql传统的btree索引并不支持模糊匹配,因此无论是‘网络%’  这样前置模糊,还是’%网络%’ 这样全模糊查询都不会走索引。 **解决方案一:为指定字段创建索引时,添加指定操作符**        pgsql可以在Btree索引上指定操作符:text\_pattern\_ops、varchar\_pattern\_ops和 bpchar\_pattern\_ops,它们分别对应字段类型text、varchar和 char,官方解释为“它们与默认操作符类的区别是值的比较是严格按照字符进行而不是根据区域相关的排序规则。这使得这些操作符类适合于当一个数据库没有使用标准“C”区域时,被使用在涉及模式匹配表达式(LIKE或POSIX正则表达式)的查询中。        因此,需要给需要模糊搜索的字段重新加上指定操作符的索引: `CREATE INDEX index_attack_alarm_event_desc ON "public"."alerts" (event_desc varchar_pattern_ops);` ``` [postgres@izwz91quxhnlkan8kjak5hz ~]$ psql psql (13.0) Type "help" for help. postgres=# select * from pg_indexes where tablename='alerts' and indexname='index_attack_alarm_event_desc'; schemaname | tablename | indexname | tablespace | indexdef ------------+-----------+-------------------------------+------------+-------------------------------------------------------------------------------------- public | alerts | index_attack_alarm_event_desc | | CREATE INDEX index_attack_alarm_event_desc ON public.alerts USING btree (event_desc) (1 row) postgres=# drop index index_attack_alarm_event_desc postgres-# \g DROP INDEX postgres=# CREATE INDEX index_attack_alarm_event_desc ON "public"."alerts" (event_desc varchar_pattern_ops); CREATE INDEX postgres=# select * from pg_indexes where tablename='alerts' and indexname='index_attack_alarm_event_desc'; schemaname | tablename | indexname | tablespace | indexdef ------------+-----------+-------------------------------+------------+---------------------------------------------------------------------------------------------------------- public | alerts | index_attack_alarm_event_desc | | CREATE INDEX index_attack_alarm_event_desc ON public.alerts USING btree (event_desc varchar_pattern_ops) (1 row) ``` **结果测试**:        下图可见,这种方式创建索引后,相同语句的模糊搜索是有经过索引的 ![](https://img.kancloud.cn/ab/06/ab062a9874d7e6f52325d9671f0da492_787x629.png) **方案缺点:**        这种方式创建的索引虽然可以解决’网络%’这种后模糊查询的不经过索引问题,但是 ‘%网络’和‘%网络%’这两种模糊查询方式(前=后置模糊和全模糊)依然会不经过索引,如下图所示: ![](https://img.kancloud.cn/f0/52/f0525bfb4d91914329fff058121fedf3_712x489.png) **解决方案二:使用pg_trgm扩展解决模糊查询不走索引的问题** > Pgsql有"pg\_trgm"和"pg\_bigm"这两个扩展库,“pg\_tigm”为pgsql官方提供的索引,"pg\_bigm"为日本开发者提供。pg\_bigm是基于pg\_trgm开发的。 如果需求需要实现全模糊和后置模糊,可以考虑引入这两个扩展库后,再创建扩展与索引: ``` CREATE EXTENSION pg_trgm; CREATE EXTENSION pg_bigm; ``` 具体实现详见 [pgsql的pg_trgm扩展解析与验证](http://docs.linchunyu.top/2280101)