Greenplum 2000亿 近似度查询 性能 以及注意事项

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云原生多模数据库 Lindorm,多引擎 多规格 0-4节点
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
简介:

greenplum和PostgreSQL一样,都是通过pg_trgm来支持近似度查询的。
原理是将字符串前加2空格,末尾加1空格,然后按照3个连续的字符串为一组,打散成多个字符串。然后计算字符串的重复度来计算两个字符串的相似度。
计算重复度时,需要进行去重复的操作。
例如:

postgres=# select similarity('abcde','abcabc');  
 similarity   
------------  
   0.333333  
(1 row)  
Time: 0.413 ms  

以上两个字符串被拆分成如下token(以下-代表空格)
--a, -ab, abc, bcd, cde, de-
--a, -ab, abc, bca, cab, abc, bc-
两者token去重后的集合为
--a, -ab, abc, bcd, cde, de-, bca, cab, bc-
重复的token为
--a, -ab, abc
所以abcde 和 abcabc 的近似度=3/9=0.333333

greenplum安装pg_trgm也很简单。

cd gpsrc/contrib/pg_trgm/  

现在有个bug需要手工fix一下

vi trgm.h  
#define TRGMINT(a) ( (*(((char*)(a))+2)<<16)+(*(((char*)(a))+1)<<8)+*(((char*)(a))+0) )  
  
make && make install  
  
gpscp -f ./host /home/digoal/gphome/lib/postgresql/pg_trgm.so =:/home/digoal/gphome/lib/postgresql/pg_trgm.so  
gpscp -f ./host /home/digoal/gphome/share/postgresql/contrib/uninstall_pg_trgm.sql =:/home/digoal/gphome/share/postgresql/contrib/uninstall_pg_trgm.sql  
gpscp -f ./host /home/digoal/gphome/share/postgresql/contrib/pg_trgm.sql =:/home/digoal/gphome/share/postgresql/contrib/pg_trgm.sql  
  
psql -f /home/digoal/gphome/share/postgresql/contrib/pg_trgm.sql  

测试

postgres=# create table t(info text);  
NOTICE:  Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'info' as the Greenplum Database data distribution key for this table.  
HINT:  The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.  
CREATE TABLE  
postgres=# insert into t select md5(random()::text) from generate_series(1,100);  
INSERT 0 100  
postgres=# select * from t limit 10;  
               info                 
----------------------------------  
 2d33d6379b85eb7a3c4090dce7a0ebe2  
 75b4be956b90f8a8c528f847eddd34fe  
 ae7f1bb726486fba174cfc27a90ea080  
 b714894688f9ef9272c61d09efebb361  
 d8774ded2bad3c4aafb85cc98fea7d06  
 afdc717a7e4c73e22a497db9c2812bfa  
 eda761ac73f659072ae2084268d5f2fe  
 e2660e7b3a9a7824611c4af93bc2c4d9  
 8659bdb87b3f5d3e6d7f269233e12d4b  
 fd28ec09a46d2f35b3b3461ab48d1998  
(10 rows)  

当前的近似度阈值为0.3,当两个字符串的近似度小于0.3时,返回false。

postgres=# select show_limit();  
 show_limit   
------------  
        0.3  
(1 row)  
  
postgres=# select '2d33d6379b85eb7a3c4090dce7a0ebe2' % 'eb7a3c409';  
 ?column?   
----------  
 f  
(1 row)  
  
postgres=# select * from t where info % 'eb7a3c409';  
 info   
------  
(0 rows)  

使用set_limit可以设置近似度阈值

postgres=# select set_limit(0.1);  
 set_limit   
-----------  
       0.1  
(1 row)  
  
postgres=# select '2d33d6379b85eb7a3c4090dce7a0ebe2' % 'eb7a3c409';  
 ?column?   
----------  
 t  
(1 row)  
  
postgres=# select * from t where info % 'eb7a3c409';  
 info   
------  
(0 rows)  

为什么查询表的记录时没有起作用呢?
原因是set_limit()函数没有在segment上执行,它们还是0.3:

postgres=# select show_limit() from gp_dist_random('gp_id');  
 show_limit   
------------  
        0.3  
        0.3  
        0.3  
        0.3  
    ......

通过gp_dist_random强制在segment执行,

postgres=# select set_limit(0.1) from gp_dist_random('gp_id');  
 set_limit   
-----------  
       0.1  
       0.1  
       0.1  
       ......
  
postgres=# select * from t where info % 'eb7a3c409';  
               info                 
----------------------------------  
 2d33d6379b85eb7a3c4090dce7a0ebe2  
(1 row)  

由于GP有会话缓存,释放后,又需要重新和segment建立连接,这时又回到0.3了。

postgres=# select * from t where info % 'eb7a3c409';  
 info   
------  
(0 rows)  
postgres=# select show_limit() from gp_dist_random('gp_id');  
 show_limit   
------------  
        0.3  
        0.3  
        0.3  
        0.3  
    ......

以上就是greenplum的近似度查询的用法。
还支持索引哦 :
索引不受set_limit的影响,也就是说索引中不存储固定的limit值,是随时可调整的。

create index idx on t using gist (info gist_trgm_ops);

目前还不支持GIN,因为GP的GIN索引在AO表的使用方面有问题,存在同步的问题,可能导致数据不一致。

src/backend/commands/indexcmds.c
..

        /* MPP-9329: disable creation of GIN indexes */
        if (accessMethodId == GIN_AM_OID)
                ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                 errmsg("GIN indexes are not supported")));
..

预知2000亿的近似度查询性能,明天放出。

postgres=# select count(distinct info),count(*) from t_regexp_100billion ;  
   count    |    count       
------------+--------------  
 2147475713 | 212600000000  
(1 row)  
  
postgres=# explain select ctid,* from t_regexp_100billion where info >='3347597ec8' and info<'3347597ec9' and info like '3347597ec8%' limit 5;  
                                                                      QUERY PLAN                                                                         
-------------------------------------------------------------------------------------------------------------------------------------------------------  
 Limit  (cost=0.00..2479.65 rows=5 width=19)  
   ->  Gather Motion 240:1  (slice1; segments: 240)  (cost=0.00..2479.65 rows=5 width=19)  
         ->  Limit  (cost=0.00..2479.55 rows=1 width=19)  
               ->  Index Scan using idx_1 on t_regexp_100billion  (cost=0.00..396651039.36 rows=3333 width=19)  
                     Index Cond: info >= '3347597ec8'::text AND info < '3347597ec9'::text AND info >= '3347597ec8'::text AND info < '3347597ec9'::text  
                     Filter: info ~~ '3347597ec8%'::text  
 Settings:  enable_seqscan=off  
(7 rows)  
Time: 55.146 ms  
  
postgres=# select ctid,* from t_regexp_100billion where info >='3347597ec8' and info<'3347597ec9' and info like '3347597ec8%' limit 5;  
     ctid     |     info       
--------------+--------------  
 (663830,524) | 3347597ec812  
 (704622,147) | 3347597ec812  
 (682224,472) | 3347597ec812  
 (644991,150) | 3347597ec812  
 (667081,662) | 3347597ec812  
(5 rows)  
Time: 57.635 ms  
  
postgres=# explain select ctid,* from t_regexp_100billion where info >='3347597' and info<'3347598' and reverse(info)>='218c' and reverse(info)<'218d' and info like '3347597%c812' limit 5;  
                                                   QUERY PLAN                                                      
-----------------------------------------------------------------------------------------------------------------  
 Limit  (cost=0.01..304985.33 rows=5 width=19)  
   ->  Gather Motion 240:1  (slice1; segments: 240)  (cost=0.01..304985.33 rows=5 width=19)  
         ->  Limit  (cost=0.01..304985.23 rows=1 width=19)  
               ->  Index Scan using idx_2 on t_regexp_100billion  (cost=0.01..99181639.41 rows=7 width=19)  
                     Index Cond: reverse(info) >= '218c'::text AND reverse(info) < '218d'::text  
                     Filter: info >= '3347597'::text AND info < '3347598'::text AND info ~~ '3347597%c812'::text  
 Settings:  enable_seqscan=off  
(7 rows)  
Time: 55.338 ms  
  
postgres=# select ctid,* from t_regexp_100billion where info >='3347597' and info<'3347598' and reverse(info)>='218c' and reverse(info)<'218d' and info like '3347597%c812' limit 5;  
     ctid     |     info       
--------------+--------------  
 (704622,147) | 3347597ec812  
 (731733,400) | 3347597ec812  
 (774593,650) | 3347597ec812  
 (739526,433) | 3347597ec812  
 (779749,565) | 3347597ec812  
(5 rows)  
Time: 104.845 ms  
  
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
人工智能 Java Linux
『GitHub项目圈选09』推荐5款本周大佬都在用的开源项目
『GitHub项目圈选09』推荐5款本周大佬都在用的开源项目
391 1
|
Linux API 内存技术
Linux Kernel中AEP的现状和发展
AEP简介AEP是Intel推出的一种新型的非易失Optane Memory设备,又被称作Apache Pass,所以一般习惯称作AEP。在这之前也有类似的设备称作NVDIMM或PMEM,目前Linux创建的AEP设备节点也是叫做pmem(如/dev/pmem0),所以本文中NVDIMM或PMEM都指AEP。
4852 0
|
1月前
|
人工智能 前端开发 JavaScript
Gemini CLI 架构学习指南
本指南深入解析开源终端AI助手Gemini CLI的架构设计,涵盖项目结构、核心流程与技术栈(TypeScript/React+Ink/Node.js),并提供从环境搭建到贡献代码的四阶段学习路径,助力开发者掌握AI编程工具开发精髓。
260 3
|
存储 NoSQL 关系型数据库
|
6月前
|
人工智能 数据库 Anolis
偶遇龙蜥,2025 OceanBase 开发者大会即将在广州举办
龙蜥社区邀您共赴一场属于开发者的“数据库+AI”技术Party。
|
监控 Java API
SpringBoot 2.0 + 阿里巴巴 Sentinel 动态限流实战
前言 在从0到1构建分布式秒杀系统和打造十万博文系统中,限流是不可缺少的一个环节,在系统能承受的范围内既能减少资源开销又能防御恶意攻击。 在前面的文章中,我们使用了开源工具包 Guava 提供的限流工具类 RateLimiter 和 OpenResty 的 Lua 脚本分别进行 API 和应用层面的限流。
3223 0
|
8月前
|
数据采集 Web App开发 JavaScript
Jsoup 爬虫:轻松搞定动态加载网页内容
Jsoup 爬虫:轻松搞定动态加载网页内容
|
9月前
|
机器学习/深度学习 人工智能 供应链
2024年的供应链回顾与2025展望:数字化转型与韧性提升
2024年的供应链回顾与2025展望:数字化转型与韧性提升
|
存储 关系型数据库 MySQL
|
12月前
|
传感器 机器学习/深度学习 算法
车速检测
车速检测是现代交通管理和自动驾驶的关键技术,通过雷达、激光和计算机视觉等手段,实现对车辆速度的精准测量。本文重点介绍了利用计算机视觉中的目标检测(如YOLO)与跟踪算法(如CSRT)进行车速检测的方法,包括目标检测、跟踪及速度计算的具体步骤,展示了该技术在智能交通系统中的应用价值。