标签

PostgreSQL , 文本相似 , 并行相似查询 , merge sort , 合并排序 , append scan 并行 , 相似地址 , 相似问题 , 相似兴趣 , 相似搜索


背景

在现实生活中,很多地方会用到相似搜索,例如

1、打车,要去某个地方,我们输入的目的地可能和数据库里面存的并不完全一致。所以只能通过相似搜索来实现。

2、搜索问题,同样的道理,我们搜的问题可能和存的问题不完全一致。只能通过相似搜索来匹配。

3、搜索兴趣点,等。

实际上PostgreSQL就可以支持相似搜索,包括图片、数组、文本等相似搜索。对于文本,可以使用pg_trgm插件来实现相似搜索。

这是纯英文字符串的测试,100亿量级(每行32个随机英文字母+数组的组合),模糊查询毫秒级别。

《PostgreSQL 百亿数据 秒级响应 正则及模糊查询》

相似查询使用同样的插件和索引。本文针对随机中文,相似搜索进行测试,看看PostgreSQL 单机性能如何?

构建测试样本数据

1、生成随机中文的函数

-- 生成随机汉字符串
create or replace function gen_hanzi(int) returns text as $$
declare    res text;
begin    if $1 >=1 then    select string_agg(chr(19968+(random()*20901)::int), '') into res from generate_series(1,$1);    return res;    end if;    return null;
end;
$$ language plpgsql strict;

2、使用分区表来提高写入、查询性能

如何建分区表,请参考:

《PostgreSQL 查询涉及分区表过多导致的性能问题 - 性能诊断与优化(大量BIND, spin lock, SLEEP进程)》

《PostgreSQL 商用版本EPAS(阿里云ppas) - 分区表性能优化 (堪比pg_pathman)》

《PostgreSQL 传统 hash 分区方法和性能》

《PostgreSQL 10 内置分区 vs pg_pathman perf profiling》

《PostgreSQL 10.0 preview 功能增强 - 内置分区表》

本文为了测试方便,未使用以上分区方法,请注意。

3、建父表(为了加速导入,使用了unlogged table,生成请勿使用)

create unlogged table tbl(id int primary key, info text);  alter table tbl set (parallel_workers =64);  create extension pg_trgm;

4、建64个子表

do language plpgsql $$
declare
begin  for i in 0..63  loop  execute format('drop table if exists tbl%s ', i);  execute format('create unlogged table tbl%s (like tbl including all) inherits(tbl)', i);  -- 提前设置好表级并行度,方便后面做并行测试  execute format('alter table tbl%s set (parallel_workers =64)', i);  end loop;
end;
$$;

5、往分区中写入10亿条测试数据

快速写入方法如下,使用dblink异步调用并行加载。

create or replace function conn(    name,   -- dblink名字    text    -- 连接串,URL
) returns void as $$
declare
begin      perform dblink_connect($1, $2);     return;
exception when others then      return;
end;
$$ language plpgsql strict;

64个分区,每行64个随机汉字,每个分区写入15625000行,总共插入10亿行。

create extension dblink;  do language plpgsql $$
declare
begin  for i in 0..63  loop  perform conn('link'||i,  'hostaddr=127.0.0.1 user=postgres dbname=postgres');   perform dblink_send_query('link'||i, format('insert into tbl%s select generate_series(1, 15625000), gen_hanzi(64)', i));  end loop;
end;
$$;

这种并行写入方法,把CPU用了个精光,马力全开,高速写入10亿条随机文本。

top - 14:49:48 up 217 days,  4:29,  3 users,  load average: 64.33, 63.08, 46.16
Tasks: 756 total,  65 running, 691 sleeping,   0 stopped,   0 zombie
%Cpu(s): 96.5 us,  3.5 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 52807456+total,  7624988 free, 19696912 used, 50075267+buff/cache
KiB Swap:        0 total,        0 free,        0 used. 37125398+avail Mem

写入完毕:

10亿记录,表占用空间223GB,写入记录耗时18分钟。

样本如下:

postgres=# select * from tbl limit 10;  id |                                                               info
----+----------------------------------------------------------------------------------------------------------------------------------  1 | 懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁内橰畁蜫征瘭缆竟  2 | 荓嚅鑀鑬抾诐裹坲雚囻卥饸數拰絔刦霨礸诿廓琫颧仯瞱捲瘰弶瓴鹝逼倭舌飂陭盒寚芘怦敍种椡檱玠肙羡兎蒿眤粆焙蟸儌樛裦窽美影诳哜帪粊圊鈵疧  3 | 齷楣莁艪箉髎岒險旚舲瞞靻薀岹滺扡習坍敮鯭鈳鈫篖刀繹芲截孞讼咺茅讎瀝曡湓鶦戊糥钫秤彲沤熻雲筝銵妮宊鰂焜埒躐採薨銐鐚梶唕俓响寏蓘鉛緬  4 | 鶹愈篭怞迭烲调侺辖帘颬歎儨劵磘鼪痐芪踖譱梮脁翦荣蠖膹訰闥曬糦琬攀迮偳真耷獦捼臱捗玕竷肥皽羬姘癃嗗躂撴鍉垊鞵玊賮耦喞睹癦溊咺鲒薋隨  5 | 鼅崄眹狆犁妅蠝頖虼椝漮暄瓴靰湛揑屿懿浛咏螈媤蚴輦萝嵵帋諗婢閖臙姂勵奮纈睶擳最濧鵯舜鄕摎坫裠蒩洽靟颧貘鷮肋餼蓽瀌綴鑳耗棦估瘈鲿嫲竾  6 | 嚈譺勏浺勔璶歅蛰春膒遜你暖巳颿徙鲋霈鈣阣籡把琲焮钢輗牞欅谱罐頃钹欤鳑抏濸燢翓坄訇懁馠譧穗埮蒂诰哔篥繮鳷墡鋸熃篏蟵惶予单鼧翘鵗鐻鳼  7 | 骄圥浏況裸皓圣鲹炎钊睫穼祧掶腐喧鐤红恈蝷傀踗濇捶躟甜拸滒狎垎氩涭悳譸豭鮬执閐飀蓴詵炆忋搷蘼錛毞窻爘縦抌璘沙葓訍宓姊鼅籥纘囯骎鹄榢  8 | 虢謌斩髈胷廄耘毇腊釣臾柡蕙丷钛埋繝垃繣鳶跖棋壤馟栬蝉碒焚舲眱貽棯抙勀搒閐掄阪憲雎表閯弊減闦吀矦璞嶃嚤燯鵘煯糓靓讛摷灀崐颩饱鯍懳層  9 | 仨砆剏摬溋昁宕坍尋沟睨剌犟侩磫舢塎鳚翕箽稈瞂枲避駂盃覄鎎狪鵷偍珒痘咜訾陣沝韔下窨擎睳绵襭礜堺毩荪啰鶾徂腸疛礴牒澹偒就探甼娃旯鬎臛  10 | 沌薧碙謩緖碤昬钣偱霠繫箎侶鱔归圦驭烔誝灣鰈嵋鈜鹚歼嘘珰睿済潙妵貓啛葎砗蔱嵍遂稰徾螾壶赌襴喥麞銙偭濍綒狐氰賜敇櫤墳浟郕舲赧悉跧穕柤
(10 rows)

6、创建索引(实际生产中,索引可以先建好,这里主要是为了加速生成速度)

do language plpgsql $$
declare
begin  create index idx_tbl_info on tbl using gin(info gin_trgm_ops);  for i in 0..63  loop  perform conn('link'||i,  'hostaddr=127.0.0.1 user=postgres dbname=postgres');   perform dblink_send_query('link'||i, format('create index idx_tbl%s_info on tbl%s using gin(info gin_trgm_ops);', i, i));  end loop;
end;
$$;

10亿记录,GIN倒排索引占用空间332GB,创建索引耗时接近180分钟。

索引创建速度解释:

由于这个CASE写入的字符串是几万个汉字里面的完全随机的汉字,所以GIN倒排索引的TOKEN特别多。这个CASE比正常生产数据的索引要大很大,正常索引不会这么大,正常创建速度也会比这个快。但是创建GIN索引的速度相比BTREE确实是要慢很多的(结构所致)。如果是BTREE索引,应该会在5分钟内创建完成。

相似查询SQL用法

1、查看当前相似度阈值

select show_limit();  show_limit
------------  0.3
(1 row)

2、设置当前会话相似度阈值,其他设置详见末尾部分

select set_limit(0.9);

3、相似搜索的响应速度与用户设置的相似度有关,用户设置的相似度匹配到的值越多,速度越慢。匹配到的值越少(即精度越高),响应速度越快。

-- 响应速度更慢
postgres=# select set_limit(0.1);  set_limit
-----------  0.1
(1 row)  -- 响应速度更快
postgres=# select set_limit(0.9);  set_limit
-----------  0.9
(1 row)

4、根据输入文本,查询与之相似的文本,并按相似排序输出。

select similarity(info, '输入搜索词') as sml, -- 计算输入词与存储字符串的相似度  * from tbl   where info % '输入搜索词'    -- 相似度超过阈值  order by sml desc            -- 按相似度排序(倒排,越相似的排在越前面)  limit 10;

SQL耗时:71毫秒

postgres=# select set_limit(0.7);  set_limit
-----------  0.7
(1 row)  select similarity(info, '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁') as sml, -- 计算输入词与存储字符串的相似度  * from tbl   where info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'    -- 相似度超过阈值  order by sml desc            -- 按相似度排序(倒排,越相似的排在越前面)  limit 10;    sml  | id |                                                               info
------+----+----------------------------------------------------------------------------------------------------------------------------------  0.75 |  1 | 懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁内橰畁蜫征瘭缆竟
(1 row)  Time: 71.627 ms

5、SQL执行计划如下,使用到了索引扫描,所以非常快。

explain select similarity(info, '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁') as sml, -- 计算输入词与存储字符串的相似度  * from tbl   where info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'    -- 相似度超过阈值  order by sml desc            -- 按相似度排序(倒排,越相似的排在越前面)  limit 10;   QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------  Limit  (cost=1025136.11..1025137.35 rows=10 width=204)  ->  Gather Merge  (cost=1025136.11..1148791.31 rows=999944 width=204)  Workers Planned: 8  ->  Sort  (cost=1024135.97..1024448.45 rows=124993 width=204)  Sort Key: (similarity(tbl2.info, '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)) DESC  ->  Result  (cost=554.09..1021434.91 rows=124993 width=204)  ->  Parallel Append  (cost=554.09..1019872.50 rows=124993 width=200)  ->  Parallel Bitmap Heap Scan on tbl2  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl2_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl3  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl3_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl4  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl4_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl5  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl5_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl7  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl7_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl8  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl8_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl9  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl9_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl10  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl10_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl11  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl11_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl12  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl12_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl13  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl13_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl14  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl14_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl16  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl16_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl17  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl17_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl18  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl18_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl19  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl19_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl20  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl20_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl21  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl21_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl22  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl22_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl23  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl23_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl24  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl24_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl25  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl25_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl26  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl26_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl28  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl28_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl29  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl29_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl30  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl30_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl31  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl31_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl33  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl33_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl34  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl34_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl35  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl35_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl36  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl36_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl37  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl37_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl38  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl38_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl39  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl39_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl41  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl41_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl42  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl42_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl44  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl44_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl45  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl45_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl46  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl46_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl47  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl47_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl48  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl48_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl49  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl49_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl50  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl50_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl51  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl51_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl52  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl52_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl53  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl53_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl55  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl55_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl56  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl56_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl57  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl57_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl58  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl58_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl59  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl59_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl61  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl61_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl62  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl62_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl63  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl63_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl0  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl0_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl1  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl1_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl6  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl6_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl15  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl15_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl27  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl27_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl32  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl32_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl40  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl40_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl43  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl43_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl54  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl54_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Bitmap Heap Scan on tbl60  (cost=554.09..15935.51 rows=1953 width=200)  Recheck Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Bitmap Index Scan on idx_tbl60_info  (cost=0.00..550.19 rows=15625 width=0)  Index Cond: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)  ->  Parallel Seq Scan on tbl  (cost=0.00..0.00 rows=1 width=36)  Filter: (info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'::text)
(265 rows)

6、强制使用并行,PostgreSQL 11支持多个分区并行执行,速度将更快。

set enable_parallel_append =on;
set max_parallel_workers_per_gather =16;
set parallel_setup_cost =0;
set parallel_tuple_cost =0;
set min_parallel_table_scan_size =0;
set min_parallel_index_scan_size =0;
set enable_parallel_append =on;
postgres=# select set_limit(0.7);  set_limit
-----------  0.7
(1 row)  explain select similarity(info, '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁') as sml, -- 计算输入词与存储字符串的相似度  * from tbl   where info % '懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁'    -- 相似度超过阈值  order by sml desc            -- 按相似度排序(倒排,越相似的排在越前面)  limit 10;

加了并行后,SQL耗时:40毫秒(因为本来就已经很快了,所以加并行度性能几乎没有提高,当计算量很大时,性能会提升明显)

 sml  | id |                                                               info
------+----+----------------------------------------------------------------------------------------------------------------------------------  0.75 |  1 | 懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁内橰畁蜫征瘭缆竟
(1 row)  Time: 40.298 ms

相似查询性能压测

1、构建压测函数,从现有记录中,使用主键随机提取一条字符串(并加工处理,生成一个新的具有一定相似度的字符串)。

使用 substring(info,1,28)||gen_hanzi(4)||substring(info,29,28) 将得到相似度为0.75的一个新字符串。

从第1位开始,取28位,然后插入4个随机中文,再从29位开始取28位。这个字符串作为相似查询的输入。相似度为0.75。  postgres=# select substring(info,1,28)||gen_hanzi(4)||substring(info,29,28) newval, info, similarity(substring(info,1,28)||gen_hanzi(4)||substring(info,29,28) , info) from tbl limit 10;
-[ RECORD 1 ]--------------------------------------------------------------------------------------------------------------------------------
newval     | 懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦焳邹祧鵅莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁
info       | 懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁内橰畁蜫征瘭缆竟
similarity | 0.75
-[ RECORD 2 ]--------------------------------------------------------------------------------------------------------------------------------
newval     | 荓嚅鑀鑬抾诐裹坲雚囻卥饸數拰絔刦霨礸诿廓琫颧仯瞱捲瘰弶瓴叠濷賨櫕鹝逼倭舌飂陭盒寚芘怦敍种椡檱玠肙羡兎蒿眤粆焙蟸儌樛裦窽美
info       | 荓嚅鑀鑬抾诐裹坲雚囻卥饸數拰絔刦霨礸诿廓琫颧仯瞱捲瘰弶瓴鹝逼倭舌飂陭盒寚芘怦敍种椡檱玠肙羡兎蒿眤粆焙蟸儌樛裦窽美影诳哜帪粊圊鈵疧
similarity | 0.75
-[ RECORD 3 ]--------------------------------------------------------------------------------------------------------------------------------
newval     | 齷楣莁艪箉髎岒險旚舲瞞靻薀岹滺扡習坍敮鯭鈳鈫篖刀繹芲截孞熒镻缮蜝讼咺茅讎瀝曡湓鶦戊糥钫秤彲沤熻雲筝銵妮宊鰂焜埒躐採薨銐鐚
info       | 齷楣莁艪箉髎岒險旚舲瞞靻薀岹滺扡習坍敮鯭鈳鈫篖刀繹芲截孞讼咺茅讎瀝曡湓鶦戊糥钫秤彲沤熻雲筝銵妮宊鰂焜埒躐採薨銐鐚梶唕俓响寏蓘鉛緬
similarity | 0.75

压测函数如下

-- 使用随机字符串进行相似搜索(用于压测)
create or replace function get_tbl(int) returns setof record as
$$
declare    str text;
begin    perform set_limit(0.7);  -- 从第1位开始,取28位,然后插入4个随机中文,再从29位开始取28位。这个字符串作为相似查询的输入。相似度为0.75。  select substring(info,1,28)||gen_hanzi(4)||substring(info,29,28) into str from tbl where id=$1 limit 1;      return query execute format($_$select similarity(info, %L) as sml,   -- 计算输入词与存储字符串的相似度  * from tbl   where info %% %L             -- 相似度超过阈值  order by sml desc            -- 按相似度排序(倒排,越相似的排在越前面)  limit 10$_$,  str, str);
end;
$$ language plpgsql strict;

查询测试

postgres=# select * from get_tbl(1) as t(sml float4, id int, info text);  sml  | id |                                                               info
------+----+----------------------------------------------------------------------------------------------------------------------------------  0.75 |  1 | 懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁内橰畁蜫征瘭缆竟
(1 row)  Time: 92.229 ms

压测脚本

vi test.sql
\set id random(1,15625000)
select * from get_tbl(1) as t(sml float4, id int, info text);

压测

-- 并行度调低
alter role postgres set max_parallel_workers_per_gather =2;  pgbench -M prepared -n -r -P 1 -f ./test.sql -c 32 -j 32 -T 120  transaction type: ./test.sql
scaling factor: 1
query mode: prepared
number of clients: 64
number of threads: 64
duration: 120 s
number of transactions actually processed: 51503
latency average = 149.175 ms
latency stddev = 20.054 ms
tps = 428.589421 (including connections establishing)
tps = 428.699150 (excluding connections establishing)
statement latencies in milliseconds:0.003  \set id random(1,15625000)149.311  select * from get_tbl(1) as t(sml float4, id int, info text);

性能瓶颈分析:

1、CPU跑满,IO也蛮高

top - 19:32:05 up 217 days,  9:11,  3 users,  load average: 38.04, 21.38, 11.92
Tasks: 768 total,  57 running, 710 sleeping,   0 stopped,   1 zombie
%Cpu(s): 82.0 us, 12.8 sy,  0.0 ni,  4.1 id,  1.1 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 52807456+total, 11373780 free, 14563392 used, 50213737+buff/cache
KiB Swap:        0 total,        0 free,        0 used. 35995504+avail Mem

CPU耗费主要是bitmapscan, cpu进行tuple recheck造成。

IO耗费,主要是数据+索引已经接近600GB,超过了内存大小,涉及到大量的IO访问。

小结

数据构造性能指标:

10亿文本数据写入耗时: 18分钟。

GIN索引生成耗时: 180分钟。

空间占用:

10亿文本: 223 GB

索引: 332 GB

性能指标:

CASE 单次相似搜索响应速度 整机压测相似搜索TPS 整机压测相似搜索RT
10亿行,每行64个随机中文 40毫秒 428 149毫秒

CPU跑满,IO也蛮高

CPU耗费主要是bitmapscan, cpu进行tuple recheck造成。

IO耗费,主要是数据+索引已经接近600GB,超过了内存大小,涉及到大量的IO访问。

小结

1、PostgreSQL 11 , append 并行,使得性能有大幅度提升。

10亿条随机中文字符串(长度64)的相似搜索,耗时仅XXX秒。

postgres=# show enable_parallel_append ;  enable_parallel_append
------------------------  on
(1 row)

2、本例子使用分区表的好处:

2.1、数据写入并行度提高,

2.2、创建索引变快,

2.3、维护索引也变快。

同时PostgreSQL 11已经支持多个分区并行扫描(enable_parallel_append),同时支持了并行+merge sort,所以海量数据相似搜索的大计算量情况下性能也不是问题。

在PostgreSQL 11之前,可以使用dblink异步调用来支持多个分区的并行扫描。例子:

《PostgreSQL dblink异步调用实现 并行hash分片JOIN - 含数据交、并、差 提速案例》

3、相似搜索中很关键的一个点是相似度,通过show_limit()可以查看相似度限制,通过set_limit可以设置相似度阈值。相似度值越大,表示需要的匹配度越高,1表示完全匹配。

postgres=# select show_limit();  show_limit
------------  0.3
(1 row)  postgres=# select set_limit(0.9);  set_limit
-----------  0.9
(1 row)

4、通过similarity或word_similarity可以查看两个字符串的相似度值。

postgres=# select similarity('abc','abcd');  similarity
------------  0.5
(1 row)  postgres=# select word_similarity('abc','abcd');  word_similarity
-----------------  0.75
(1 row)  postgres=# select word_similarity('abc','abc');  word_similarity
-----------------  1
(1 row)  postgres=# select similarity('abc','abc');  similarity
------------  1
(1 row)

相似算法详情请参考

https://www.postgresql.org/docs/devel/static/pgtrgm.html

5、响应速度与用户设置的相似度有关,用户设置的相似度匹配到的值越多,速度越慢。匹配到的值越少(即精度越高),响应速度越快。

-- 响应速度更慢
postgres=# select set_limit(0.1);  set_limit
-----------  0.1
(1 row)  -- 响应速度更快
postgres=# select set_limit(0.9);  set_limit
-----------  0.9
(1 row)

实际生产中使用,我们可以先使用高的limit去搜索,逐渐缩小这个阈值,从而达到较快响应速度。这个逻辑可以封装到UDF中,用户调用UDF即可进行搜索。

例子

create or replace function get_res(text, int8) returns setof record as $$
declare  lim float4 := 1;
begin  loop  -- 设置相似度阈值  perform set_limit(lim);  -- 查看当前阈值下,有没有相似记录  perform similarity(info, $1) as sml, * from tbl where info % $1 limit 1;  -- 如果有,则返回N条  if found then  return query select similarity(info, $1) as sml, * from tbl where info % $1 order by sml desc limit $2;  return;  end if;  -- 否则继续,降低阈值  -- 当阈值小于0.3时,不再降阈值搜索,认为没有相似。  if lim < 0.3 then  return;  else  lim := lim - 0.1;  end if;  end loop;
end;
$$ language plpgsql strict;
select * from get_res('输入搜索文本', 输入限制条数) as t(sml float4, id int, info text);

使用这个UDF搜索,既快又准。

postgres=# select * from get_res('罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦莥钶们鞀楝嬦眥条', 10) as t(sml float4, id int, info text);  sml    | id |                                                               info
----------+----+----------------------------------------------------------------------------------------------------------------------------------0.455882 |  1 | 懛瑌娺罊鶩凳芹緔茙蠡慺礛唾霹蹺憙胣緗犭昉鬪蒽麴牵癰嚒巈蔦莥钶们鞀楝嬦眥条弘娸霵鐲鑚夊涨鮗傞屽嶋莁豓舸鮉蟙材骘媨迁内橰畁蜫征瘭缆竟
(1 row)Time: 202.229 ms

6、如果要设置PG实例、数据库、用户级的阈值,可以通过这两个参数来指定

pg_trgm.similarity_threshold  pg_trgm.word_similarity_threshold

他们分别作用于以下操作符和函数(详见 https://www.postgresql.org/docs/devel/static/pgtrgm.html )。

text % text
similarity(text, text)  与  text <% text
word_similarity(text, text)

设置举例

postgres=# alter system set pg_trgm.similarity_threshold =0.9;
ALTER SYSTEM  postgres=# select pg_reload_conf();  pg_reload_conf
----------------  t
(1 row)  -- 永久生效  postgres=# show pg_trgm.similarity_threshold;  pg_trgm.similarity_threshold
------------------------------  0.9
(1 row)

参考

《PostgreSQL 查询涉及分区表过多导致的性能问题 - 性能诊断与优化(大量BIND, spin lock, SLEEP进程)》

《PostgreSQL 商用版本EPAS(阿里云ppas) - 分区表性能优化 (堪比pg_pathman)》

《PostgreSQL 传统 hash 分区方法和性能》

《PostgreSQL 10 内置分区 vs pg_pathman perf profiling》

《PostgreSQL 10.0 preview 功能增强 - 内置分区表》

《PostgreSQL 全文检索之 - 位置匹配 过滤语法(例如 '速度 <1> 激情')》

《PostgreSQL 模糊查询 与 正则匹配 性能差异与SQL优化建议》

《PostgreSQL 遗传学应用 - 矩阵相似距离计算 (欧式距离,...XX距离)》

《多流实时聚合 - 记录级实时快照 - JSON聚合与json全文检索的功能应用》

《PostgreSQL - 全文检索内置及自定义ranking算法介绍 与案例》

《用PostgreSQL 做实时高效 搜索引擎 - 全文检索、模糊查询、正则查询、相似查询、ADHOC查询》

《HTAP数据库 PostgreSQL 场景与性能测试之 17 - (OLTP) 数组相似查询》

《HTAP数据库 PostgreSQL 场景与性能测试之 16 - (OLTP) 文本特征向量 - 相似特征(海明...)查询》

《HTAP数据库 PostgreSQL 场景与性能测试之 14 - (OLTP) 字符串搜索 - 全文检索》

《HTAP数据库 PostgreSQL 场景与性能测试之 13 - (OLTP) 字符串搜索 - 相似查询》

《HTAP数据库 PostgreSQL 场景与性能测试之 12 - (OLTP) 字符串搜索 - 前后模糊查询》

《HTAP数据库 PostgreSQL 场景与性能测试之 9 - (OLTP) 字符串模糊查询 - 含索引实时写入》

《HTAP数据库 PostgreSQL 场景与性能测试之 7 - (OLTP) 全文检索 - 含索引实时写入》

《多国语言字符串的加密、全文检索、模糊查询的支持》

《Greenplum 模糊查询 实践》

《全文检索 不包含 优化 - 阿里云RDS PostgreSQL最佳实践》

《17种文本相似算法与GIN索引 - pg_similarity》

《PostgreSQL 模糊查询最佳实践 - (含单字、双字、多字模糊查询方法)》

《PostgreSQL 10.0 preview 功能增强 - JSON 内容全文检索》

《PostgreSQL结合余弦、线性相关算法 在文本、图片、数组相似 等领域的应用 - 3 rum, smlar应用场景分析》

《PostgreSQL结合余弦、线性相关算法 在文本、图片、数组相似 等领域的应用 - 2 smlar插件详解》

《PostgreSQL结合余弦、线性相关算法 在文本、图片、数组相似 等领域的应用 - 1 文本(关键词)分析理论基础 - TF(Term Frequency 词频)/IDF(Inverse Document Frequency 逆向文本频率)》

《导购系统 - 电商内容去重\内容筛选应用(实时识别转载\盗图\侵权?) - 文本、图片集、商品集、数组相似判定的优化和索引技术》

《PostgreSQL 全表 全字段 模糊查询的毫秒级高效实现 - 搜索引擎颤抖了》

《从难缠的模糊查询聊开 - PostgreSQL独门绝招之一 GIN , GiST , SP-GiST , RUM 索引原理与技术背景》

《从相似度算法谈起 - Effective similarity search in PostgreSQL》

《聊一聊双十一背后的技术 - 毫秒分词算啥, 试试正则和相似度》

《PostgreSQL 全文检索加速 快到没有朋友 - RUM索引接口(潘多拉魔盒)》

《PostgreSQL 文本数据分析实践之 - 相似度分析》

《中文模糊查询性能优化 by PostgreSQL trgm》

《PostgreSQL 行级 全文检索》

《PostgreSQL 百亿数据 秒级响应 正则及模糊查询》

《PostgreSQL chinese full text search 中文全文检索》

《聊一聊双十一背后的技术 - 毫秒分词算啥, 试试正则和相似度》

《PostgreSQL 1000亿数据量 正则匹配 速度与激情》

毫秒级相似搜索设计与实现 - 地址、QA、POI等文本相似搜索相关推荐

  1. 【Elasticsearch】搜索自己想要的东西与注释文本(字符串)插件

    1.概述 翻译:https://www.elastic.co/cn/blog/search-for-things-not-strings-with-the-annotated-text-plugin ...

  2. 京东毫秒级热key探测框架设计与实践,已完美支撑618大促

    在拥有大量并发用户的系统中,热key一直以来都是一个不可避免的问题.或许是突然某些商品成了爆款,或许是海量用户突然涌入某个店铺,或许是秒杀时瞬间大量开启的爬虫用户, 这些突发的无法预先感知的热key都 ...

  3. android 访问内网ip_android 获取局域网IP与MAC 地址 毫秒级(详解)

    两个 linux命令 开始理清思路:主要使用 linux 两个命令(2017-07-21 fix:这个思路不好,后面使用udp取代[毫秒级]) [ping]: 查询某个ip是否被设备占用 [cat]  ...

  4. 毫秒级查询的离线IP地址定位库,太实用了!

      大家好,我是为广大程序员兄弟操碎了心的小编,每天推荐一个小工具/源码,装满你的收藏夹,每天分享一个小技巧,让你轻松节省开发效率,实现不加班不熬夜不掉头发,是我的目标!   咱们程序员开发任何系统, ...

  5. NFTScan x TiDB丨一栈式 HTAP 数据库为 Web3 数据服务提供毫秒级多维查询

    导读 NFTScan 是一家多链 NFT 数据基础设施服务商,为 Web3 用户提供高效简洁的 NFT 资产搜索查询服务,为 Web3 开发者和新一代金融科技公司提供专业的 NFT API 数据服务. ...

  6. 1.3 万亿条数据查询,知乎如何做到毫秒级响应?

    (给视学算法加星标,提升数据技能) 作者:孙晓光 http://itindex.net/ 知乎搜索后端负责人,目前承担知乎搜索后端架构设计以及工程团队的管理工作.曾多年从事私有云相关产品开发工作,关注 ...

  7. 百亿数据,毫秒级返回,如何构建?

    前言 大家好,我是坤哥,今天我想和大家聊一聊实时索引的构建之道,来自我司 PB 级索引数据的实战经验,相信对大家肯定有帮助. 近年来公司业务迅猛发展,数据量爆炸式增长,随之而来的的是海量数据查询等带来 ...

  8. ELK搭建毫秒级响应社工裤

    by:linshao 前述: mysql由于锁机制等等对于大量数据里查找某几条的操作是非常耗时的,索引虽然能大大加快查询的速度,但是需要新增一些内存用于存放索引, ELK是一款主流的日志平台架构,分布 ...

  9. lg g3 com.Android,毫秒级激光辅助对焦 2K屏幕LG G3评测

    在三星.索尼以及HTC等国际厂商之后,LG也终于推出了上半年的旗舰产品--LG G2的升级款G3:虽然并没有传说中的自产处理器的加入,而且在外形设计上基本也与LG G2一脉相承,不过软件方面的更新还是 ...

最新文章

  1. 6425C-Lab6 实现组策略
  2. Matlab与C++混合编程(依赖OpenCV)
  3. python列表切片得到的是列表还是字符串_python中列表的切片问题 python arry怎么取列切片...
  4. CSDN Markdown编辑器编辑教程
  5. [js] 纯函数和函数式编程有什么关系?
  6. RabbitMq--AMQP高级消息队列协议--简单了解
  7. Chapter 3 Phenomenon——13
  8. Decision Tree决策树练习题
  9. qt同时两个动画执行_Qt 动画应用
  10. 微信支付中证书的存放目录及其路径写法
  11. 谷歌浏览器插件安装方法 谷歌浏览器导入插件的步骤
  12. STM32的时钟系统的库函数编程总结,根据图和表理解程序
  13. Unity 鼠标进入UI控件,显示控件名称
  14. html速成项目,HTML速成教材.doc
  15. php远程控制代码,内部网络机器的远程控制软件UltraVNC及其源代码
  16. Android和蓝牙GPS结合的方法
  17. TiDB监控pd面板显示:Region Health: empty-regin-count很多,怎么回收empty-regin?
  18. Win10切换到了Users用户怎么切换回来
  19. 汽车覆盖件冲压模具铸造工艺研究
  20. Python之OpenGL笔记(17):键盘鼠标控制摄像机移动旋转

热门文章

  1. 微信小程序 跳转小程序
  2. MySQL 修改用户名和密码
  3. datagrid编辑单元格回车换行_使用EasyUI的Datagrid的Editor进行行编辑,Enter回车结束编辑,并开启新的一行。...
  4. 如何解决mac键盘不能操作的问题?
  5. 探索WebKit内核(四)------ Inspector
  6. android 相册权限_手机软件APP需要这么多权限?遇上流氓软件怎么办?
  7. window和python查看和调用exe的对照,结合pyqt5应用查找指定程序,并结束应用程序(酒馆战棋整活必备)
  8. css3-11 网页如何使用自定义字体
  9. ESG成全球风潮,联想造了一个可持续的“进托邦”
  10. 来来来,干了这碗毒鸡汤……