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

简介:

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数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
Linux API 内存技术
Linux Kernel中AEP的现状和发展
AEP简介AEP是Intel推出的一种新型的非易失Optane Memory设备,又被称作Apache Pass,所以一般习惯称作AEP。在这之前也有类似的设备称作NVDIMM或PMEM,目前Linux创建的AEP设备节点也是叫做pmem(如/dev/pmem0),所以本文中NVDIMM或PMEM都指AEP。
5286 0
|
NoSQL 索引
MongoDB查询优化:从 10s 到 10ms
本文是我前同事付秋雷最近遇到到一个关于MongoDB执行计划选择的问题,非常有意思,在探索源码之后,他将整个问题搞明白并整理分享出来。付秋雷(他的博客)曾是Tair(阿里内部用得非常官方的KV存储系统)的核心开发,目前就职于蘑菇街。
【CentOS8】 本地yum源配置
centos8系统的本地yum源配置稍稍有些不同
3315 0
【CentOS8】 本地yum源配置
|
2月前
|
人工智能 API 开发工具
最新版Qwen Code全解:核心功能详解与阿里云百炼Coding Plan、Token Plan接入教程
在AI赋能编程的浪潮中,终端级AI编程工具凭借轻量化、高效能的特性,成为开发者提升编码效率的重要选择。Qwen Code作为一款专为代码开发打造的终端AI工具,凭借强大的代码理解、生成与调试能力,以及对阿里云百炼生态的深度兼容,快速成为开发者的热门选择。最新版Qwen Code在功能上实现多项关键升级,同时提供便捷的接入方式,可无缝对接阿里云百炼的Coding Plan与Token Plan两大订阅方案,满足个人与团队不同场景的AI编程需求。本文将全面解析最新版Qwen Code的核心功能,并详细讲解接入阿里云百炼Coding Plan、Token Plan的完整流程,助力开发者快速上手,释放
333 2
|
2月前
|
人工智能 自然语言处理 Java
RAG系统测试实战:如何验证企业知识库AI助手是否可靠?
近两年,企业纷纷构建基于RAG的AI应用:不训大模型,而是将产品文档、制度流程等内部知识接入,通过检索增强生成实现智能问答。但其质量保障远超传统测试——需覆盖知识库完整性、检索准确性、生成忠实度与答案相关性等多层验证,是AI时代测试工程师的核心新能力。
RAG系统测试实战:如何验证企业知识库AI助手是否可靠?
|
2月前
|
人工智能 架构师 安全
【AI时代软件项目管理系列】2. 从工具到数字员工:AI 在项目团队中的角色演进
AI 正从个人助手演进为能够规划、调用工具并完成任务的 Agent,进一步形成多 Agent 协作与软件工厂。角色变化带来的不只是效率提升,更是团队结构、任务分配、进度衡量和质量管理方式的重构。项目经理需要把模型、Agent、知识库和自动化流程纳入统一管理,通过明确任务契约、权限边界、质量门禁与人工验收,确保 AI 执行可控、结果可验证、责任可追溯。
355 0
|
2月前
|
人工智能 搜索推荐 算法
3个信号判断内容是否被AI引用:来自知乎问答的实测观察
本文基于8周实测,揭示AI引擎引用知乎内容的3大信号:1)内容结构需具备“可提取性”,结论须前置;2)社区验证信号(赞同/收藏比、多元评论)影响可信度判定;3)持续更新显著提升引用权重。小账号亦可通过结构优化提升AI可见度。
338 0
|
存储 Linux C语言
【零基础友好】Linux 初学者指令指南:常用指令 + 实操案例,一步一步教你用(收藏级)
本教程系统讲解Linux操作系统基础操作与常用指令,涵盖账号管理、路径操作、文件处理、目录管理、文本查看、时间设置、文件搜索、压缩解压等内容,适合初学者快速掌握Linux命令行核心技能。
【零基础友好】Linux 初学者指令指南:常用指令 + 实操案例,一步一步教你用(收藏级)
|
SQL 人工智能 数据挖掘
quickbi使用总结以及问题反馈
本文总结了使用QuickBI高级版及电子表格的功能体验与改进建议。内容涵盖具体报表使用(如趋势分析表、多维趋势表)、函数及其他模块(如LOD函数、自助取数)、AI智能问数模块以及数据集使用的优缺点。指出趋势分析表在复合指标处理上的不足,多维趋势表对比周期限制,以及1万条明细数据限制对年同比的影响等问题。同时提出未来期望,希望建立结合企业知识库的大模型,优化数据分析与建议能力。
1389 46
|
数据采集 Web App开发 JavaScript
Jsoup 爬虫:轻松搞定动态加载网页内容
Jsoup 爬虫:轻松搞定动态加载网页内容

热门文章

最新文章