pgsql查询优化之模糊查询
前言
一直以来,对于搜索时模糊匹配的优化一直是个让人头疼的问题,好在强大pgsql提供了优化方案,下面就来简单谈一谈如何通过索引来优化模糊匹配
案例
我们有一张千万级数据的检查报告表,需要通过检查报告来模糊搜索某个条件,我们先创建如下索引:
CREATE INDEX lab_report_report_name_index ON lab_report USING btree (report_name);
然后搜个简单的模糊匹配条件如 LIKE "血常规%",可以发现查询计划生成如下,索引并没有被使用上,这是因为传统的btree索引并不支持模糊匹配

查阅文档后发现,pgsql可以在Btree索引上指定操作符:text_pattern_ops、varchar_pattern_ops和 bpchar_pattern_ops,它们分别对应字段类型text、varchar和 char,官方解释为“它们与默认操作符类的区别是值的比较是严格按照字符进行而不是根据区域相关的排序规则。这使得这些操作符类适合于当一个数据库没有使用标准“C”区域时被使用在涉及模式匹配表达式(LIKE或POSIX正则表达式)的查询中。”, 有些抽象,我们先试试看。创建如下索引并查询刚才的条件 LIKE"血常规%":(参考pgsql的文档 https://www.postgresql.org/docs/10/indexes-opclass.html)
CREATE INDEX lab_report_report_name_index ON lab.lab_report (report_name varchar_pattern_ops);

发现确实可以走索引扫描 ,执行时间也从213ms优化到125ms,但是,如果搜索LIKE "%血常规%"就又会走全表扫描了! 这里我们引入本篇博客的主角"pg_trgm"和"pg_bigm"。
创建这两个索引前分别需要引入如下两个扩展包 :
CREATE EXTENSION pg_trgm;
CREATE EXTENSION pg_bigm;
这两个索引的区别是:“pg_tigm”为pgsql官方提供的索引,"pg_tigm"为日本开发者提供。下面是详细的对比:(参考pg_bigm的文档 http://pgbigm.osdn.jp/pg_bigm_en-1-2.html)
Comparison with pg_trgm
The pg_trgm contrib module which provides full text search capability using 3-gram (trigram) model is included in PostgreSQL. The pg_bigm was developed based on the pg_trgm. They have the following differences:
| Functionalities and Features | pg_trgm | pg_bigm |
|---|---|---|
| Phrase matching method for full text search | 3-gram | 2-gram |
| Available index | GIN and GiST | GIN only |
| Available text search operators | LIKE (~~), ILIKE (~~*), ~, ~* | LIKE only |
| Full text search for non-alphabetic language (e.g., Japanese) |
Not supported (*1) | Supported |
| Full text search with 1-2 characters keyword | Slow (*2) | Fast |
| Similarity search | Supported | Supported (version 1.1 or later) |
| Maximum indexed column size | 238,609,291 Bytes (~228MB) | 107,374,180 Bytes (~102MB) |
- (*1) You can use full text search for non-alphabetic language by commenting out KEEPONLYALNUM macro variable in contrib/pg_trgm/pg_trgm.h and rebuilding pg_trgm module. But pg_bigm provides faster non-alphabetic search than such a modified pg_trgm.
- (*2) Because, in this search, only sequential scan or index full scan (not normal index scan) can run.
pg_bigm 1.1 or later can coexist with pg_trgm in the same database, but pg_bigm 1.0 cannot.
如无特殊要求推荐使用"pg_bigm",我们测试一下效果:
CREATE INDEX lab_report_report_name_index ON lab_report USING gin (report_name public.gin_bigm_ops);

可以使用位图索引扫描,对于本次案例,使用pg_trgm效果同pg_bigm。
以上
本文只是简单的介绍许多细节并未做深入的分析,欢迎留言指教或者讨论
pgsql查询优化之模糊查询的更多相关文章
- oracle数据库使用hint来让模糊查询走索引
在没有创建数据直方图之前,查询优化器是cbo,可能不会选择代价最低(效率最高)的方式查询. 先创建表 --日语假名表 CREATE TABLE JAPANESE_SOUNDMARK ( ID INTE ...
- Oracle 模糊查询 优化
模糊查询是数据库查询中经常用到的,一般常用的格式如下: (1)字段 like '%关键字%' 字段包含"关键字"的记录 即使在目标字段建立索引也不会走索引,速度最慢 (2 ...
- Mybatis框架的模糊查询(多种写法)、删除、添加(四)
学习Mybatis这么多天,那么我给大家分享一下我的学习成果.从最基础的开始配置. 一.创建一个web项目,看一下项目架构 二.说道项目就会想到需要什么jar 三.就是准备大配置链接Orcl数据库 & ...
- js—模糊查询
首先要明白什么是模糊查询(废话又来了),就是根据关键字把列表中符合关键字的一项或某项罗列出来,也就是要检查列表的每一项中是否含有关键字,因此抽象一下就是一个字符串中是否含有某个字符或者字符串. 以下例 ...
- mybatis : trim标签, “等于==”经验, CDATA标签 ,模糊查询CONCAT,LIKE
一.My Batis trim标签有点类似于replace效果. trim 属性, prefix:前缀覆盖并增加其内容 suffix:后缀覆盖并增加其内容 prefixOverrides:前缀判断的条 ...
- combobox实现模糊查询自动填充
利用winform设计软件界面时,经常用到combobox控件,但有时需要绑定数据表中的数据,更进一步,需要实现对数据表中数据的模糊查询功能.本文就讲讲述如何用C#实现combobox下拉列表的模糊查 ...
- [转]ORACLE中Like与Instr模糊查询性能大比拼
instr(title,'手册')>0 相当于 title like '%手册%' instr(title,'手册')=1 相当于 title like '手册%' instr(titl ...
- 关系数据库SQL之基本数据查询:子查询、分组查询、模糊查询
前言 上一篇关系数据库常用SQL语句语法大全主要是关系型数据库大体结构,本文细说一下关系型数据库查询的SQL语法. 语法回顾 SELECT [ALL|DISTINCT] <目标列表达式>[ ...
- StackExchange.Redis加载Lua脚本进行模糊查询的批量删除和修改
前言 使用StackExchange.Redis没有直接相关的方法进行模糊查询的批量删除和修改操作,虽然可以通过Scan相关的方法进行模糊查询,例如:HashScan("hashkey&qu ...
随机推荐
- 浅谈网络I/O多路复用模型 select & poll & epoll
http://blog.csdn.net/nk_test/article/details/50662946
- MinGW和MSYS区别和关系以及MinGW&MSYS在Win7中安装并编译x264
http://blog.csdn.net/freeape/article/details/50555003
- 初涉Delphi Socket编程
不是第一次接触socket编程了,但以前都是看别人的依葫芦画瓢,也不知道具体的原理. 新的项目,有了新的开始,同时也需要有新的认识. Delphi 中带有两套TCP Socket组件: Indy So ...
- C语言实现常用数据结构——栈
#include<stdio.h> #include<stdlib.h> //用链表实现栈 typedef struct Node { int data; struct Nod ...
- 为了考PMP,我做了一个刷题小程序
一.背景 1.我是一名软件工程师,技术出身,担任开发组长,对项目管理不是很熟,所以决定系统学习下项目管理. 2.全球最适合的项目管理学习课程就是PMP,每年有4次PMP考试,证书还是很有含金量的. 3 ...
- mogodbshell中数组对象查询修改方法
在mongodb中,存在如下数据 { "_id" : ObjectId("59af55078a8fc5e51ff425de"), "title&quo ...
- 解决安装Oracle本地可以访问客户端不能访问
现象:本地需要修改监听为localhost -->win+r--> sqlplus system/123@xxdb 可以登陆,远程客户端不能登陆:需要将监听修改为IP地址,重启监听:远程可 ...
- kali 开启键盘背光灯 && 自定义开启终端
新建文件保存扩展名为.sh 编辑文件,键入如下代码 #!/bin/bash - status=/tmp/keyboard_led_status if [[ ${1} == "on" ...
- IM推送保障及网络优化详解(一):如何实现不影响用户体验的后台保活
对于移动APP来说,IM功能正变得越来越重要,它能够创建起人与人之间的连接.社交类产品中,用户与用户之间的沟通可以产生出更好的用户粘性. 在复杂的 Android 生态环境下,多种因素都会造成消息推送 ...
- 【React】存储全局数据
参考链接:https://segmentfault.com/a/1190000012057010?utm_source=tag-newest webstorage webstorage是本地存储,存储 ...