PolarDB 开源基础教程系列 7.2 应用实践之 跨境电商场景

本文涉及的产品
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
云原生数据库 PolarDB MySQL 版,通用型 2核8GB 50GB
简介: 本文介绍了如何在跨境电商场景中快速判断商标或品牌侵权,避免因侵权带来的法律纠纷。通过创建品牌表并使用PostgreSQL的pg_trgm插件和GIN索引,实现了高性能的字符串相似匹配功能。与传统方法相比,PolarDB|PostgreSQL的方法不仅提升了上万倍的查询速度,还解决了传统方法难以处理的相似问题检索。具体实现步骤包括创建品牌表、插入随机品牌名、配置pg_trgm插件及索引,并设置相似度阈值进行高效查询。此外,文章还探讨了字符串相似度计算的原理及应用场景,提供了进一步优化和扩展的方向。

2、跨境电商场景, 快速判断商标|品牌侵权

b站视频链接

Youtube视频链接


2、跨境电商场景, 快速判断商标|品牌侵权

很多业务场景中需要判断商标侵权, 避免纠纷. 例如

  • 电商的商品文字描述、图片描述中可能有侵权内容. 特别是跨境电商, 在一些国家侵权查处非常严厉.
  • 注册公司名、产品名时可能侵权.
  • 在写文章时, 文章的文字内容、视频内容、图片内容中的描述可能侵权.

而且商标侵权通常还有相似的情况, 例如修改大品牌名字的其中的个别字母, 蹭大品牌的流量, 导致大品牌名誉受损.

例如postgresql是个商标, 如果你使用posthellogresql、postgresqlabc, p0stgresql也可能算侵权.

以跨境电商为力, 为了避免侵权, 在发布内容时需要商品描述中出现的品牌名、产品名等是否与已有的商标库有相似.

对于跨境电商场景, 由于店铺和用户众多, 商品的修改、发布是比较高频的操作, 所以需要实现高性能的字符串相似匹配功能.

一、准备数据

创建一张品牌表, 用于存储收集好的注册商标(通常最终转换为文字).

create unlogged table tbl_ip (   -- 测试使用unlogged table, 加速数据生成    
  id serial primary key,  -- 每一条品牌信息的唯一ID    
  n text  -- 品牌名    
);

使用随机字符模拟生成1000万条品牌名.

insert into tbl_ip (n) select md5(random()::text) from generate_series(1,10000000);

再放入几条比较容易识别的:

insert into tbl_ip(n) values ('polardb'),('polardbpg'),('polardbx'),('alibaba'),('postgresql'),('mysql'),('aliyun'),('apsaradb'),('apple'),('microsoft');
postgres=# select * from tbl_ip limit 10;    
 id |                n                     
----+----------------------------------    
  1 | f4cd4669d249c1747c1d31b0b492d84e    
  2 | 2e29f32460485698088f4ab0632d86b7    
  3 | a8460622db4a3dc4ab70a8443a2c2a1a    
  4 | c4554856e259d3dfcccfb3c9872ab1d0    
  5 | b3a6041c5838d70d95a1316eea45bea3    
  6 | fc2d701eca05c74905fd1a604f072006    
  7 | f3dc443060e33bb672dc6a3b79bc1acd    
  8 | 1305b6092f9e798453e9f60840b8db2a    
  9 | 9b07cad251661627e15f239e5b122eaf    
 10 | 8b5d2a468435febe417b17d0d0442b86    
(10 rows)    
    
postgres=# select count(*) from tbl_ip;    
  count       
----------    
 10000010    
(1 row)

二、传统方法只能使用like全模糊查询, 但是局部侵权的可能性非常多, 使用模糊查询需要很多很多组合, 性能会非常差.

例如postgresql是个商标, 如果用户使用了一个字符串为以下组合, 都可能算侵权:

  • post
  • postgres
  • sql
  • gresql
  • postgresql
  • postgre

写成SQL应该是这样的

select * from tbl_ip where    
  n like '%post%' or    
  n like '%postgres%' or    
  n like '%sql%' or    
  n like '%gresql%' or    
  n like '%postgresql%' or    
  n like '%postgre%';

结果

id    |     n          
----------+------------    
 10000005 | postgresql    
 10000006 | mysql    
(2 rows)

耗时如下

QUERY PLAN                                                                                      
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------    
 Seq Scan on tbl_ip  (cost=0.00..333336.00 rows=5999 width=37) (actual time=2622.461..2622.463 rows=2 loops=1)    
   Filter: ((n ~~ '%post%'::text) OR (n ~~ '%postgres%'::text) OR (n ~~ '%sql%'::text) OR (n ~~ '%gresql%'::text) OR (n ~~ '%postgresql%'::text) OR (n ~~ '%postgre%'::text))    
   Rows Removed by Filter: 10000008    
 Planning Time: 1.381 ms    
 JIT:    
   Functions: 2    
   Options: Inlining false, Optimization false, Expressions true, Deforming true    
   Timing: Generation 1.442 ms, Inlining 0.000 ms, Optimization 1.561 ms, Emission 6.486 ms, Total 9.489 ms    
 Execution Time: 2624.001 ms    
(9 rows)

三、基于 PolarDB|PostgreSQL 特性的设计和实验

使用pg_trgm插件, gin索引, 以及它的字符串相似查询功能,

创建插件

postgres=# create extension if not exists pg_trgm;    
NOTICE:  extension "pg_trgm" already exists, skipping    
CREATE EXTENSION

创建索引

postgres=# create index on tbl_ip using gin (n gin_trgm_ops);

设置相似度阈值, 仅返回相似度大于0.9的记录

postgres=# set pg_trgm.similarity_threshold=0.9;    
SET

使用相似度查询

select *,     
  similarity(n, 'post'),    
  similarity(n, 'postgres'),    
  similarity(n, 'sql'),    
  similarity(n, 'gresql'),    
  similarity(n, 'postgresql'),    
  similarity(n, 'postgre')    
from tbl_ip     
where    
  n % 'post' or    
  n % 'postgres' or    
  n % 'sql' or    
  n % 'gresql' or    
  n % 'postgresql' or    
  n % 'postgre';

结果

id    |     n      | similarity | similarity | similarity | similarity | similarity | similarity     
----------+------------+------------+------------+------------+------------+------------+------------    
 10000005 | postgresql | 0.33333334 |  0.6666667 | 0.15384616 |  0.3846154 |          1 |  0.5833333    
(1 row)

耗时如下

QUERY PLAN                                                                                
------------------------------------------------------------------------------------------------------------------------------------------------------------------    
 Bitmap Heap Scan on tbl_ip  (cost=996.70..7365.20 rows=5999 width=37) (actual time=0.180..0.183 rows=1 loops=1)    
   Recheck Cond: ((n % 'post'::text) OR (n % 'postgres'::text) OR (n % 'sql'::text) OR (n % 'gresql'::text) OR (n % 'postgresql'::text) OR (n % 'postgre'::text))    
   Heap Blocks: exact=1    
   ->  BitmapOr  (cost=996.70..996.70 rows=6000 width=0) (actual time=0.140..0.141 rows=0 loops=1)    
         ->  Bitmap Index Scan on tbl_ip_n_idx  (cost=0.00..115.30 rows=1000 width=0) (actual time=0.053..0.053 rows=0 loops=1)    
               Index Cond: (n % 'post'::text)    
         ->  Bitmap Index Scan on tbl_ip_n_idx  (cost=0.00..200.00 rows=1000 width=0) (actual time=0.019..0.019 rows=0 loops=1)    
               Index Cond: (n % 'postgres'::text)    
         ->  Bitmap Index Scan on tbl_ip_n_idx  (cost=0.00..93.30 rows=1000 width=0) (actual time=0.007..0.007 rows=0 loops=1)    
               Index Cond: (n % 'sql'::text)    
         ->  Bitmap Index Scan on tbl_ip_n_idx  (cost=0.00..157.10 rows=1000 width=0) (actual time=0.011..0.011 rows=0 loops=1)    
               Index Cond: (n % 'gresql'::text)    
         ->  Bitmap Index Scan on tbl_ip_n_idx  (cost=0.00..242.90 rows=1000 width=0) (actual time=0.035..0.035 rows=1 loops=1)    
               Index Cond: (n % 'postgresql'::text)    
         ->  Bitmap Index Scan on tbl_ip_n_idx  (cost=0.00..179.10 rows=1000 width=0) (actual time=0.013..0.013 rows=0 loops=1)    
               Index Cond: (n % 'postgre'::text)    
 Planning Time: 4.682 ms    
 Execution Time: 0.272 ms    
(18 rows)

使用了pg_trgm后, 即使是like查询响应速度也飞快:

postgres=# explain analyze select * from tbl_ip where    
  n like '%post%' or    
  n like '%postgres%' or    
  n like '%sql%' or    
  n like '%gresql%' or    
  n like '%postgresql%' or    
  n like '%postgre%';    
                                                                                     QUERY PLAN                                                                                         
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------    
 Bitmap Heap Scan on tbl_ip  (cost=612.80..6981.30 rows=5999 width=37) (actual time=0.122..0.126 rows=2 loops=1)    
   Recheck Cond: ((n ~~ '%post%'::text) OR (n ~~ '%postgres%'::text) OR (n ~~ '%sql%'::text) OR (n ~~ '%gresql%'::text) OR (n ~~ '%postgresql%'::text) OR (n ~~ '%postgre%'::text))    
   Heap Blocks: exact=1    
   ->  BitmapOr  (cost=612.80..612.80 rows=6000 width=0) (actual time=0.099..0.101 rows=0 loops=1)    
         ->  Bitmap Index Scan on tbl_ip_n_idx  (cost=0.00..50.40 rows=1000 width=0) (actual time=0.047..0.048 rows=1 loops=1)    
               Index Cond: (n ~~ '%post%'::text)    
         ->  Bitmap Index Scan on tbl_ip_n_idx  (cost=0.00..136.20 rows=1000 width=0) (actual time=0.011..0.011 rows=1 loops=1)    
               Index Cond: (n ~~ '%postgres%'::text)    
         ->  Bitmap Index Scan on tbl_ip_n_idx  (cost=0.00..29.50 rows=1000 width=0) (actual time=0.003..0.003 rows=2 loops=1)    
               Index Cond: (n ~~ '%sql%'::text)    
         ->  Bitmap Index Scan on tbl_ip_n_idx  (cost=0.00..93.30 rows=1000 width=0) (actual time=0.014..0.014 rows=1 loops=1)    
               Index Cond: (n ~~ '%gresql%'::text)    
         ->  Bitmap Index Scan on tbl_ip_n_idx  (cost=0.00..179.10 rows=1000 width=0) (actual time=0.014..0.014 rows=1 loops=1)    
               Index Cond: (n ~~ '%postgresql%'::text)    
         ->  Bitmap Index Scan on tbl_ip_n_idx  (cost=0.00..115.30 rows=1000 width=0) (actual time=0.008..0.008 rows=1 loops=1)    
               Index Cond: (n ~~ '%postgre%'::text)    
 Planning Time: 0.571 ms    
 Execution Time: 0.207 ms    
(18 rows)

四、传统方法与PolarDB|PostgreSQL的对照

品牌数 传统like查询耗时 ms PolarDB|PostgreSQL pg_trgm近似查询耗时 ms PolarDB|PostgreSQL pg_trgm like查询耗时 ms
1000万条 2624.001 0.272 0.207

毫无疑问, PolarDB|PostgreSQL性能提升了上万倍, 而且解决了传统方法无法解决的相似问题检索.

五、知识点

1、pg_trgm

https://www.postgresql.org/docs/16/pgtrgm.html

如何计算两个字符串的相似度:

  • 1、切词. 非字母或数字都被认为是word分隔符, 将字符串拆分成若干个word.
  • 2、将word转换成token. 在每个word的前面加2个空格, 每个word的末尾加1个空格, 然后以连续的三个字符为一组, 从头开始切, 将每个" word "切分为若干个“3个字符的token”.
  • 3、去除重复token, 得到一组token.
  • 4、根据token来计算2个字符串的相似性. 注意有不同的算法.

将字符串转换生成token的例子:

-- 第一步得到two和words, 然后得到"  two "和"  words ", 然后得到以下.     
postgres=# select show_trgm('two ,words');      
                       show_trgm                           
-------------------------------------------------------    
 {"  t","  w"," tw"," wo","ds ",ord,rds,two,"wo ",wor}    
(1 row)    
    
postgres=# select show_trgm('two , words');    
                       show_trgm                           
-------------------------------------------------------    
 {"  t","  w"," tw"," wo","ds ",ord,rds,two,"wo ",wor}    
(1 row)    
    
postgres=# select show_trgm(' two , words   ');    
                       show_trgm                           
-------------------------------------------------------    
 {"  t","  w"," tw"," wo","ds ",ord,rds,two,"wo ",wor}    
(1 row)    
    
-- 结果token会去重      
postgres=# select show_trgm('two two1');       
             show_trgm                 
-----------------------------------    
 {"  t"," tw","o1 ",two,"wo ",wo1}    
(1 row)    
    
postgres=# select show_trgm('two');    
        show_trgm            
-------------------------    
 {"  t"," tw",two,"wo "}    
(1 row)    
    
postgres=# select show_trgm('words');    
            show_trgm                
---------------------------------    
 {"  w"," wo","ds ",ord,rds,wor}    
(1 row)    
    
postgres=# select show_trgm('abc');    
        show_trgm            
-------------------------    
 {"  a"," ab",abc,"bc "}    
(1 row)    
    
postgres=# select show_trgm('abc hello');    
                       show_trgm                           
-------------------------------------------------------    
 {"  a","  h"," ab"," he",abc,"bc ",ell,hel,llo,"lo "}    
(1 row)

比较两个字符串相似性的算法: 详见 contrib/pg_trgm/trgm_op.c

1: similarity (%) (t % 'word'  ==> 计算相似性对应  similarity(t, 'word'))

相似性 = 两个字符串的token交集去重后的个数 / 两个字符串的token并集去重后的个数

大致可以表达: 两个字符串的整体相似性.

阈值参数: pg_trgm.similarity_threshold (real)

2: word_similarity (<% and %>) ('word' <% t  ==> 计算相似性对应  word_similarity('word', t))

word_similarity(string1, string2) == count.匹配string1 token的(token(substring(string2中的任意连续的word组))) / count(token(string1))

大致可以表达: 字符串2的若干连续字符与字符串1的相似度.

阈值参数: pg_trgm.word_similarity_threshold (real)

3: strict_word_similarity (<<% and %>>) ('word' <<% t  ==> 计算相似性对应  strict_word_similarity('word', t))

strict_word_similarity(string1, string2) == max( similarity(string1, string2中的任意连续的word组) )

大致可以表达: 字符串2的若干连续单词与字符串1的相似度.

相似度阈值参数, 相似度大于阈值时, 对应的相似操作符返回true的结果.

阈值参数: pg_trgm.strict_word_similarity_threshold (real)

计算两个字符串相似度的例子:

postgres=# select similarity('abc','abc hello');    
 similarity     
------------    
        0.4    
(1 row)    
postgres=# select similarity('abc hello','abc');    
 similarity     
------------    
        0.4    
(1 row)    
    
word_similarity    
    
    
postgres=# select word_similarity('abc','abc hello');    
 word_similarity     
-----------------    
               1    
(1 row)    
    
postgres=# select word_similarity('abc hello','abc');    
 word_similarity     
-----------------    
             0.4    
(1 row)    
    
strict_word_similarity    
    
    
postgres=# select strict_word_similarity('abc','abc hello');    
 strict_word_similarity     
------------------------    
                      1    
(1 row)    
    
    
postgres=# select strict_word_similarity('abc hello','abc');    
 strict_word_similarity     
------------------------    
                    0.4    
(1 row)    
    
    
postgres=# select similarity('word', 'wor ord');    
 similarity     
------------    
      0.625    
(1 row)    
    
postgres=# select similarity('word', 'ord wor');    
 similarity     
------------    
      0.625    
(1 row)    
    
postgres=# select word_similarity('word', 'ord wor');    
 word_similarity     
-----------------    
               1    
(1 row)    
    
postgres=# select word_similarity('word', 'wor ord');    
 word_similarity     
-----------------    
           0.625    
(1 row)    
    
postgres=# select strict_word_similarity('word', 'wor ord');    
 strict_word_similarity     
------------------------    
                  0.625    
(1 row)    
    
postgres=# select strict_word_similarity('word', 'ord wor');    
 strict_word_similarity     
------------------------    
                  0.625    
(1 row)

六、思考

为什么传统方法与pg_trgm相比性能相差这么大?

字符串近似查询还可以应用于哪些场景?

前后模糊查询优化方法?

如果将相似度调低, 性能还能这么好吗?

如果想返回最相似的一条, 怎么优化查询效果最佳? 《PostgreSQL 相似搜索设计与性能 - 地址、QA、POI等文本 毫秒级相似搜索实践》

和smlar插件相比, 搜索算法是否有相似之处?

还有哪些相似算法? 《PolarDB 开源版通过pg_similarity实现17种文本相似搜索 - token归一切分, 根据文本相似度检索相似文本.》

语义/情感相似怎么实现? vector

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
运维 Oracle 关系型数据库
免费下载! 《OceanBase 社区版入门到实战》 快人一步,成为游刃有余的分布式数据库专家!
原生分布式关系型数据库OceanBase ,具备多租户、高可用、水平扩展、高性能、低成本、兼容 ORACLE 和 MySQL 六大特点,支撑了支付宝和网商银行全部的核心业务,以及外部银行、保险、证券、运营商、央企等多个行业数百家客户的核心业务系统。OceanBase 在 2021年6月份发布了社区版 3.1,更全面有力的推动数据库生态系统建设。
104329 1
免费下载! 《OceanBase 社区版入门到实战》 快人一步,成为游刃有余的分布式数据库专家!
|
1天前
|
搜索推荐 关系型数据库 分布式数据库
PolarDB 开源基础教程系列 7.3 应用实践之 精准营销场景
本文介绍了基于用户画像的精准营销技术,重点探讨了如何通过标签组合快速圈选目标人群。实验分为三部分: 1. **传统方法**:使用字符串存储标签并进行模糊查询,但性能较差,每次请求都需要扫描全表。 2. **实验1**:引入`pg_trgm`插件和GIN索引,显著提升了单个模糊查询条件的性能。 3. **实验2**:改用数组类型存储标签,并结合GIN索引加速包含查询,性能进一步提升。 4. **实验3**:利用`smlar`插件实现近似度过滤,支持按标签重合数量或比例筛选。
16 3
|
1天前
|
存储 关系型数据库 分布式数据库
PolarDB 开源基础教程系列 1 架构解读
PolarDB 是阿里云研发的云原生分布式数据库,基于 PostgreSQL 开源版本,旨在解决传统数据库在大规模数据和高并发场景下的性能和扩展性问题。其主要特点包括: 1. **存储计算分离架构**:通过将计算与存储分离,实现极致弹性、共享一份数据以降低成本、透明读写分离。 2. **HTAP 架构**:支持混合事务处理和分析处理(HTAP),能够在同一系统中高效执行 OLTP 和 OLAP 查询。 3. **优化的日志复制机制**:采用只复制元数据的方式减少网络传输量,优化页面回放和 DDL 锁回放过程。 4. **并行查询与索引创建**:引入 MPP 分布式执行引擎。
22 7
|
1天前
|
关系型数据库 分布式数据库 数据库
PolarDB 开源基础教程系列 9 开源社区合作和共建
本文介绍了玩转 PolarDB 开源社区指南:如何搭建 PolarDB 开发环境及参与开源社区。 主要内容: 1. **搭建开发环境**:提供多种 Docker 镜像供开发者选择,支持 x86_64 和 ARM64 架构,适配 CentOS、Debian、Ubuntu 等多个 Linux 发行版。 2. **编译与部署**:通过 Docker 容器克隆 PolarDB 源码并编译安装,支持构建一写多读集群测试 ePQ MPP 优化器功能。 3. **参与开源社区**:介绍个人、生态伙伴和用户如何从社区中获取技能、建立连接、积累战绩并提升影响力。社区活动涵盖公开课、训练营、编程大赛、企业行等。
23 5
|
1天前
|
关系型数据库 分布式数据库 数据安全/隐私保护
PolarDB 开源基础教程系列 5 高级特性体验
PolarDB 特性解读与体验涵盖多项关键技术,包括预读/预扩展、Shared Server(建议使用连接池)、闪回表和闪回日志、弹性跨机并行查询(ePQ)及TDE透明数据加密。预读/预扩展通过批量I/O操作显著提升Vacuum、SeqScan等场景性能;Shared Server优化高并发短连接处理;闪回功能可恢复表至指定时间点;ePQ支持跨机并行查询以提高复杂查询效率;TDE确保数据存储层的安全加密。
12 1
|
5月前
|
存储 SQL 安全
应用案例|开源 PolarDB-X 在互联网安全场景的应用实践
中盾集团采用PolarDB-X云原生分布式数据库开源版本,有效解决了大数据量处理、复杂查询以及历史数据维护等难题,实现了业务的高效扩展与优化。
|
Cloud Native 关系型数据库 分布式数据库
阿里云开源数据库PolarDB分布式版入门训练营开营报名中!
阿里云开源数据库PolarDB分布式版入门训练营开营啦!本次训练营共有三个课程+四个任务,大家可根据自身情况灵活安排个人时间完成哦。
阿里云开源数据库PolarDB分布式版入门训练营开营报名中!
|
关系型数据库 分布式数据库 PolarDB
零基础PolarDB开源贡献新手教学 更有机会赢取PolarDB定制咖啡杯!
欢迎大家参与到我们的开源文档贡献,无论是文档捉虫、文档优化还是进阶的案例、代码贡献,我们都非常欢迎,快来开启你的第一次开源贡献之旅吧,前10名参与文档贡献并正式合入PR,可获得PolarDB定制咖啡杯一个!
零基础PolarDB开源贡献新手教学  更有机会赢取PolarDB定制咖啡杯!
|
运维 分布式数据库 云栖大会
PolarDB-X 开源分布式数据库进阶营玩法公告
为了帮助大家能够快速体验 PolarDB-X 新版本特性,阿里云 PolarDB-X 技术专家团队联合开发者学堂,共同打造 PolarDB-X 开源分布式数据库进阶训练营,通过本次课程您将学习到 PolarDB-X 新版本诸多重点特性,包括更高效的部署与运维方法(一键创建、审计日志、节点重搭、备份恢复、参数模版、只读实例)、数据快速导入导出、TP负载测试、分区管理、数据TTL过期自动删除、冷热数据归档、读写分离与HTAP等众多新特性,更有免费线上实验环境,理论学习与场景实操相结合,完成七天打卡任务将获得训练营结营证书,还有精美定制礼品等着你!
PolarDB-X 开源分布式数据库进阶营玩法公告
|
运维 Cloud Native 安全
「开源人说」|PolarDB开源未来将有哪些新动向?阿里云数据库开源负责人来解答
在10月25日由阿里云开发者社区、PolarDB开源社区、infoQ联合举办的「开源人说」第三期——《数据库PolarDB专场》沙龙上,阿里云数据库开源负责人、数据库资深技术专家王远带来了主题为《PolarDB开源现状思考和未来规划》的精彩分享。
「开源人说」|PolarDB开源未来将有哪些新动向?阿里云数据库开源负责人来解答