postgresql中文模糊查询性能优化

本文记录中文模糊查询优化的方向是 使模式匹配使用索引

有一张 2 千万多的 user 表,其中需要按照 users.chinese_name 字段进行模糊查找。

启用 pg_trgm 扩展

pg_trgm 模块提供函数和操作符测定字母,数字,文本基于三元模型匹配的相似性, 还有支持快速搜索相似字符串的索引操作符类。

这里提到了一个三元模型,其实很简单。打个比方 foo 的三元模型的集合为{" f"," fo","foo","oo "}, foo|bar 的三元模型的集合为{" f"," fo","foo","oo "," b"," ba","bar","ar "}。也就是说将字符串拆解成三个字符一组,每个字符串被认为有两个空格前缀和一个空格后缀。

Postgres 使用 trigram 将字符串分解成更小的单元便于有效地索引它们。pg_trgm 模块支持 GIST 或 GIN 索引,从 9.1 开始,这些索引支持 LIKE/ILIKE 查询。

要使用 pg_trgm 模块,首先要启用该扩展,然后使用 gin_trgm_ops 创建索引

CREATE EXTENSION pg_trgm;

创建索引

在字段上创建 GIN 类型的索引可以处理包含多个键的值,如数组等. 与 GIST 类似, GIN支持用户定义的索引策略,可以通过定义GIN索引的特定操作符类型实现不同的功能。 PostgreSQL的标准中发布了用于一维数组的GIN操作符类, 比如它支持 包含操作符 '@>'、被包含操作符 '<@'、相等操作符 '='、重叠操作符 '&&',等等。

但是这种索引对中文不起作用,需要把中文转换成字节(ASCII码),然后使用函数索引

create or replace function textsend_i (text) returns bytea as
$$

  select textsend($1);

$$
language sql strict immutable;
CREATE INDEX trgm_idx_users_chinese_name ON users USING GIN(text(textsend_i(chinese_name)) gin_trgm_ops);

查询语句

SELECT chinese_name FROM users WHERE text(textsend_i(chinese_name)) ~ ltrim(text(textsend_i('深圳')), '\x');

再优化

添加 GIN 索引后,查询性能提升很多。如上所说,GIN 不支持中文,在查询的时候,先把 chinese_name 字段转化为 bytea,然后进行匹配。这里也耽误了不少时间,我们可以在users 表上在添加一个 chinese_name_bytea 字段,存储 chinese_name 的字节形式,然后直接在该字段上进行创建 GIN 索引。也算是一种空间换取时间的方式。

ALTER TABLE users;
ADD COLUMN chinese_name_bytea VARCHAR;
UPDATE users SET chinese_name_bytes = textsend(chinese_name);
CREATE INDEX trgm_idx_users_chinese_name_bytea ON users USING GIN(chinese_name_bytea gin_trgm_ops);

查询时:

SELECT chinese_name FROM users WHERE chinese_name_bytea ~ ltrim(text(textsend_i('深圳')), '\x');
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容

  • 为什么要学习、使用C语言?为什么要学习一个可能比自己都岁数大的编程语言呢?我不知道大家有没有思考过这个问题。 ...
    枫馨蕊阅读 745评论 0 0
  • 文/清一若水 清澈的人看不到尘埃 纯净的人没有烦恼 就像流水一样 尽管安心于梦想的前方 欢乐与欢快充满了 一路的色...
    清一若水阅读 460评论 0 4
  • 通常,孩子怕老师的表现在幼儿园和小学阶段比较多。这个阶段的小孩,自尊意识已经形成,特别在乎来自家长、老师的评...
    静水观澜阅读 14,009评论 0 2
  • 生活有时就像白开水, 加糖会甜,加盐会涩, 只要适合自己就好。 感情有时就像泼墨画, 增一分浓,减一分素, 只要恰...
    届小宛阅读 346评论 0 11