PostgreSQL模糊匹配走索引的操作

场景 lower(name) like 'pf%'

create table users (id int primary key, name varchar(255));
Create or replace function random_string(length integer) returns text as
$$
declare
 chars text[] := '{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}';
 result text := '';
 i integer := 0;
begin
 if length < 0 then
 raise exception 'Given length cannot be less than 0';
 end if;
 for i in 1..length loop
 result := result || chars[1+random()*(array_length(chars, 1)-1)];
 end loop;
 return result;
end;
$$ language plpgsql;
insert into users values(generate_series(1,50000), random_string(15));

普通bt:不走索引

pg_trgm模块提供函数和操作符测定字母数字文本基于三元模型匹配的相似性,还有支持快速搜索相似字符串的索引操作符类。三元模型是一组从一个字符串中获得的三个连续的字符。我们可以通过计数两个字符串共享的三元模型的数量来测量它们的相似性。这个简单的想法证明在测量许多自然语言词汇的相似性时是非常有效的。

CREATE INDEX users_idx0 ON users (name);

全字匹配查询(走索引)

explain select * from users where name='pfDNQVmhqDrF1EY';
        QUERY PLAN
-------------------------------------------------------------------------
 Index Scan using users_idx0 on users (cost=0.29..8.31 rows=1 width=20)
 Index Cond: ((name)::text = 'pfDNQVmhqDrF1EY'::text)
(2 rows)

加函数全字匹配(不走索引)

explain select * from users where lower(name)='pfDNQVmhqDrF1EY';
      QUERY PLAN
-----------------------------------------------------------
 Seq Scan on users (cost=0.00..1069.00 rows=250 width=20)
 Filter: (lower((name)::text) = 'pfDNQVmhqDrF1EY'::text)
(2 rows)

模糊匹配(不走索引)

explain select * from users where name like 'pf%';
      QUERY PLAN
--------------------------------------------------------
 Seq Scan on users (cost=0.00..944.00 rows=5 width=20)
 Filter: ((name)::text ~~ 'pf%'::text)
explain select * from users where name like 'pf_';
      QUERY PLAN
--------------------------------------------------------
 Seq Scan on users (cost=0.00..944.00 rows=5 width=20)
 Filter: ((name)::text ~~ 'pf_'::text)

字段带函数的bt索引:函数走索引

drop index users_idx0;
CREATE INDEX users_dex1 ON users (lower(name));

加函数全字匹配(走索引)

explain select * from users where lower(name)='pfDNQVmhqDrF1EY';
        QUERY PLAN
---------------------------------------------------------------------------
 Bitmap Heap Scan on users (cost=6.23..324.34 rows=250 width=20)
 Recheck Cond: (lower((name)::text) = 'pfDNQVmhqDrF1EY'::text)
 -> Bitmap Index Scan on users_dex1 (cost=0.00..6.17 rows=250 width=0)
   Index Cond: (lower((name)::text) = 'pfDNQVmhqDrF1EY'::text)
(4 rows)

模糊匹配(不走索引)

explain select * from users where lower(name) like 'pf%';
      QUERY PLAN
-----------------------------------------------------------
 Seq Scan on users (cost=0.00..1069.00 rows=250 width=20)
 Filter: (lower((name)::text) ~~ 'pf%'::text)
(2 rows)

声明操作符类的bt索引:like走索引

定义索引的同时可以为索引的每个字段声明一个操作符类。

CREATE INDEX name ON table (column opclass [sort options] [, …]);

这个操作符类指明该索引用于该字段时要使用的操作符。

CREATE INDEX users_dex2 ON users (lower(name) varchar_pattern_ops);

模糊匹配(走索引)

explain select * from users where lower(name) like 'pf%';
            QUERY PLAN
------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on users (cost=4.82..144.00 rows=5 width=20)
 Filter: (lower((name)::text) ~~ 'pf%'::text)
 -> Bitmap Index Scan on users_dex2 (cost=0.00..4.82 rows=53 width=0)
   Index Cond: ((lower((name)::text) ~>=~ 'pf'::text) AND (lower((name)::text) ~<~ 'pg'::text))
(4 rows)

场景2 name like '%pf%'

Create or replace function random_string(length integer) returns text as
$$
declare
 chars text[] := '{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}';
 result text := '';
 i integer := 0;
begin
 if length < 0 then
 raise exception 'Given length cannot be less than 0';
 end if;
 for i in 1..length loop
 result := result || chars[1+random()*(array_length(chars, 1)-1)];
 end loop;
 return result;
end;
$$ language plpgsql;
create table users (id int primary key, name varchar(255));
insert into users values(generate_series(1,50000), random_string(15));

声明操作符bt:不走索引

CREATE INDEX idx_name ON users USING btree (lower(name) varchar_pattern_ops);
explain (analyze true,format yaml, verbose true, buffers true) select * from users where lower(name) like '%pf%';\
      QUERY PLAN
-----------------------------------------------------------
 - Plan:             +
  Node Type: "Seq Scan"        +
  Parallel Aware: false        +
  Relation Name: "users"        +
  Schema: "public"          +
  Alias: "users"          +
  Startup Cost: 0.00         +
  Total Cost: 1069.00         +
  Plan Rows: 5           +
  Plan Width: 20          +
  Actual Startup Time: 0.320       +
  Actual Total Time: 86.841       +
  Actual Rows: 710          +
  Actual Loops: 1          +
  Output:            +
  - "id"            +
  - "name"           +
  Filter: "(lower((users.name)::text) ~~ '%pf%'::text)"+
  Rows Removed by Filter: 49290      +
  Shared Hit Blocks: 319        +
  Shared Read Blocks: 0        +
  Shared Dirtied Blocks: 0        +
  Shared Written Blocks: 0        +
  Local Hit Blocks: 0         +
  Local Read Blocks: 0         +
  Local Dirtied Blocks: 0        +
  Local Written Blocks: 0        +
  Temp Read Blocks: 0         +
  Temp Written Blocks: 0        +
 Planning Time: 0.188         +
 Triggers:            +
 Execution Time: 86.975

声明pg_trgm操作符bt:可以走索引

CREATE EXTENSION pg_trgm;
CREATE INDEX idx_users_name_trgm_gist ON users USING gist (name gist_trgm_ops);
explain (analyze true, verbose true, buffers true) select * from users where name like '%pf%';
                QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on public.users (cost=32.19..371.08 rows=505 width=20) (actual time=19.314..53.132 rows=193 loops=1)
 Output: id, name
 Recheck Cond: ((users.name)::text ~~ '%pf%'::text)
 Rows Removed by Index Recheck: 49807
 Heap Blocks: exact=319
 Buffers: shared hit=972
 -> Bitmap Index Scan on idx_users_name_trgm_gist (cost=0.00..32.06 rows=505 width=0) (actual time=19.175..19.175 rows=50000 loops=1)
   Index Cond: ((users.name)::text ~~ '%pf%'::text)
   Buffers: shared hit=653
 Planning time: 0.188 ms
 Execution time: 53.231 ms
(11 rows)

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • PostgreSQL 性能优化之服务器参数配置操作

    大家好!我是只谈技术不剪发的 Tony 老师.今天我们来聊聊 PostgreSQL 的性能优化:数据库优化是一个系统的工程,本文只专注于服务器的参数配置优化. 默认安装时,PostgreSQL 的配置参数通常都偏小,不太适合作为生产服务器使用.所以,安装 PostgreSQL 数据库之后首先需要执行的操作就是对服务器的配置参数进行调整. 查看/设置参数值 我们使用 PostgreSQL 12,服务器的配置参数有 300 多个,运行时的参数值可以使用 SHOW 命令查看: show server_

  • postgresql 除法保留小数位的实例

    我就废话不多说了,大家还是直接看代码吧~ \x select 8/(100-3) as c1, round(8/(100-3) ,4) as c2, round(8/(100-3)::numeric ,4) as c3, 8/(100-3)::numeric as c4 ; -[ RECORD 1 ]-------------- c1 | 0 c2 | 0.0000 c3 | 0.0825 c4 | 0.08247422680412371134 (1 row) 补充:PostgreSQL整数除法

  • PostgreSQL忘记postgres账号密码的解决方法

    PostgreSQL简介 PostgreSQL是一个功能非常强大的.源代码开放的客户/服务器关系型数据库管理系统(RDBMS).PostgreSQL最初设想于1986年,当时被叫做Berkley Postgres Project.该项目一直到1994年都处于演进和修改中,直到开发人员Andrew Yu和Jolly Chen在Postgres中添加了一个SQL(Structured Query Language,结构化查询语言)翻译程序,该版本叫做Postgres95,在开放源代码社区发放. 下面

  • postgresql 计算距离的实例(单位直接生成米)

    之前用的是ST_Distance 函数,但是貌似需要进行一次单位的转换,而且网上有说那种转换不是特别准确,现在暂时将该算法记录在此: select st_distance(ST_GeomFromText('POINT(120.451737 36.520975)',900913),ST_GeomFromText('POINT(120.455636 36.520885)',900913))*60*1.852; 这里的计算方式倒是可以换坐标系,但是,测试了两个坐标系都没有起作用.而且该种方式转换过单位

  • Postgresql的select优化操作(快了200倍)

    对于庞大的数据,检索sql的编写要格外小心,有很多平时不注意的sql可能就会变成瓶颈. 比如, 我们有个系统, 其中t96_pd_log表,记录数8000w多,在开发阶段乃至用了那么多年都没问题, 最近却发生频繁死锁的问题, 查数据库后台发现问题出在一个select语句上, 它耗时高达2.4-2.7s,这对于一个需要高并发的系统来说当然是致命的. 数据表t96_pd_log有两条index, 一条的字段组成是f96_mgtbarcd,另一条的字段组成是f96_result_type, 检索sql

  • postgresql关于like%xxx%的优化操作

    任何一个关系型数据库关于模糊匹配(like)的优化都是一件痛苦的事,相对而言,诸如like 'abc%'之类的还好一点,可以通过创建索引来优化,但对于like 'c%'之类的,真的就没有办法了. 这里介绍一种postgresql关于like 'c%'的优化方法,是基于全文检索的特性来实现的. 测试数据准备(环境centos6.5 + postgresql 9.6.1). postgres=# create table ts(id int,name text); CREATE TABLE post

  • PostgreSQL模糊匹配走索引的操作

    场景 lower(name) like 'pf%' create table users (id int primary key, name varchar(255)); Create or replace function random_string(length integer) returns text as $$ declare chars text[] := '{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,

  • postgresql模糊匹配大杀器(推荐)

    ArteryBase-模糊匹配大杀器 问题背景 随着pg越来越强大,abase目前已经升级到5.0(postgresql10.4),目前abase5.0继承了全文检索插件(zhparser),使用全文检索越来越方便.本文会对abase支持的like模糊匹配,全文检索,创建何种索引,如何使用进行说明.针对于各种模糊匹配均可走索引 前模糊匹配(%xxx),后模糊匹配(xxx%) 使用场景:如果简单的前模糊匹配或者后模糊匹配则可以建一个简单的btree索引. --1.后模糊匹配(xxx%) creat

  • ORACLE数据库对long类型字段进行模糊匹配的解决思路

    1.背景介绍 最近在查询数据时,突然遇到了这样一个场景,如何对一个字段类型为long的字段进行模糊匹配.一顿操作以后发现不能使用like进行模糊查询,仔细查看了一下官方文档才发现,long数据类型并不支持该操作.然后就想着将long类型转换为varchar类型然后在进行模糊匹配,通过百度尝试了多种方法,发现效果不太理想.(如果你们发现好的方法欢迎在评论区留言) 2.解决思路 笔者这里采用的思路是: 先创建一个新表,然后将关键信息通过数据类型转换为合适的类型(此处是运用to_lob函数将long类

  • mysql如何让左模糊查询也能走索引

    目录 让左模糊查询也能走索引 测试表USER_INFO表数据以及结构如下 有一个USER_NAME字段的索引 模糊查询(like.instr) 1. like 2. instr 3. A>=’’ and A<’’ 3的补充讲解 让左模糊查询也能走索引 测试表USER_INFO表数据以及结构如下 有一个USER_NAME字段的索引 有个业务需求,需要模糊搜索出用户名后几位有杰这个词的所有用户信息,这时候不可能说为了一个搜索就引入ES,但是如果sql使用左模糊查询的话,根据索引的最左匹配原则,该s

  • PostgreSql 重建索引的操作

    PostgreSql数据库的重建索引时通过REINDEX命令来实现的,如reindexindex_name: 其语法是: REINDEX { INDEX | TABLE | DATABASE | SYSTEM } name [ FORCE ]; 下面解释下说明情况下需要: 1.当由于软件bug或者硬件原因导致的索引不再可用,索引的数据不再可用: 2.当索引包含许多空的或者近似于空的页,这个在b-tree索引会发生.Reindex会腾出空间释放哪些无用的页(页就是存放数据的一个单位,类似于bloc

  • python pandas模糊匹配 读取Excel后 获取指定指标的操作

    1.首先读取Excel文件 数据代表了各个城市店铺的装修和配置费用,要统计出装修和配置项的总费用并进行加和计算: 2.pandas实现过程 import pandas as pd #1.读取数据 df = pd.read_excel(r'./data/pfee.xlsx') print(df) cols = list(df.columns) print(cols) #2.获取含有装修 和 配置 字段的数据 zx_lists=[] pz_lists=[] for name in cols: if

  • PostgreSQL教程(八):索引详解

    一.索引的类型: PostgreSQL提供了多 种索引类型:B-Tree.Hash.GiST和GIN,由于它们使用了不同的算法,因此每种索引类型都有其适合的查询类型,缺省时,CREATE INDEX命令将创建B-Tree索引.         1. B-Tree:   复制代码 代码如下: CREATE TABLE test1 (         id integer,         content varchar     );     CREATE INDEX test1_id_index

  • SqlServer2016模糊匹配的三种方式及效率问题简析

    本文实例讲述了SqlServer2016模糊匹配的三种方式及效率问题.分享给大家供大家参考,具体如下: 数据库是Sqlserver 2016版 现在业务需求是:要查询出企业名称为以下几个的,XXX,XXXX等等: 第一种方式:like '%XXX%' OR like '%XXXX%' select cName from tAccountAuditing where cName like '%测试moa000154%' OR cName like '%测试集团上海事业部%' and activeA

  • Python批量模糊匹配的3种方法实例

    目录 前言 使用编辑距离算法进行模糊匹配 使用fuzzywuzzy进行批量模糊匹配 fuzz模块 process模块 整体代码 使用Gensim进行批量模糊匹配 Gensim简介 使用词袋模型直接进行批量相似度匹配 使用TF-IDF主题向量变换后进行批量相似度匹配 同时获取最大的3个结果 完整代码 总结 前言 当然,基于排序的模糊匹配(类似于Excel的VLOOKUP函数的模糊匹配模式)也属于模糊匹配的范畴,但那种过于简单,不是本文讨论的范畴. 本文主要讨论的是以公司名称或地址为主的字符串的模糊

  • mysql or走索引加索引及慢查询的作用

    目录 前言 一 概述 二 实验表结构声明 三 Mysql不走索引归类以及详细解析 1. 查询条件在索引列上使用函数操作,或者运算的情况 2. 查询条件字符串和数字之间的隐式转换 3. 特殊修饰符 %%, Or 将不走索引 4. 索引优化器选择最优的索引 四 总结以及实际应用 前言 小白白跑去鹅厂面试,面试官提出了一个很实际的问题: mysql增加索引,那些情况会失效呢?谈一下实际工作中遇到的情况.我们的小白白又抛出了白氏秘籍:用不用索引,找DBA小姐姐!啊?这是你面试哈,还是DBA小姐姐面试呀.

随机推荐