多标签搜索,后端一般是怎样实现的?不会是多表直接 join 吧?

2023-03-27 10:25:56 +08:00
 yodhcn

提到多对多关系,第一个反应是 3 张表 —— 即,两张数据表、一张关系表,例如:

t_product
| id (integer) | name (character verying) |

t_tag
| id (integer) | name (character verying) |

r_product_tag
| product_id (integer) | tag_id (integer) |

但需要根据多个 tag 查询 product 时(/product?tags=苹果,橘子),只用数据库该怎样实现?

t_product
| id (integer) | name (character verying) | tags (character verying) |

如果只按标签的 id 查询(/product?tag_ids=22,12,45),表 t_product 新增一冗余列 tag_ids (integer[]),这种情况该在此列上建立 B+树索引 还是 倒排索引

t_product
| id (integer) | name (character verying) | tag_ids (integer[]) |

不知道 PostgreSQLinteger[] 类型字段的索引机制是怎样的?

2914 次点击
所在节点    程序员
18 条回复
liprais
2023-03-27 10:38:21 +08:00
谁告诉你多表 join 效率低的?
liuzhen
2023-03-27 10:49:16 +08:00
脱离数据量说效率是耍流氓;大表 join 效率是低的,可以考虑拆 sql 多次查询,小表 join 就完事了
Ashore
2023-03-27 10:49:47 +08:00
@liprais csdn(狗头
CNife
2023-03-27 10:54:06 +08:00
建议自己实验一下,用 EXPLAIN ANALYZE 看看如何处理和代价如何
LeegoYih
2023-03-27 10:54:24 +08:00
表设计合理可以 join ,走索引性能不会差,如果是微服务或者后续需要分库分表还是拆分成三次查询吧

1. select id from t_tag where name in ("苹果","橘子")
2. select product_id from r_product_tag where tag_id in (...)
3. select * from t_product where id in (...)

如果 t_tag 更新频率较低可以放缓存里
iwishing
2023-03-27 11:19:30 +08:00
有个问题,为啥多标签是交集而不是并集?搜索我一般喜欢并集,筛选喜欢交集。
zoharSoul
2023-03-27 11:23:31 +08:00
es 直接拍平了
codespots
2023-03-27 11:42:07 +08:00
@iwishing metoo
yodhcn
2023-03-27 11:45:47 +08:00
@liprais @Ashore #1

我是在看了站内的这篇帖子才产生的疑问
https://www.v2ex.com/t/767754

最后还是在 Google 找到了答案,不论是按字符串还是 int id 搜索,都得建立倒排索引。只不过针对 int[] 有更方便的扩展( intarray )
https://stackoverflow.com/questions/8242643/search-in-integer-array-in-postgres
https://www.postgresql.org/docs/current/intarray.html
TWorldIsNButThis
2023-03-27 11:54:00 +08:00
这就是 es 出现的原因
xuelu520
2023-03-27 12:01:16 +08:00
--直接将 3 张表 JOIN 在一起?感觉查询效率会很低。
这个思维就是错的。
正常情况 JOIN 查就是了,大表 JOIN 就需要 es 了。
512357301
2023-03-27 12:11:17 +08:00
效率低那是阿里巴巴提出来的吧,好像他们有个 MySQL 开发规范,不过如楼上所说,脱离数据量谈效率就是耍流氓,你一个配置表几千几万条数据,谈效率低,啧啧啧。
join 效率低说的是百万千万量级的时候效率低,这也不是 join 的锅,这是 MySQL 的锅
yodhcn
2023-03-27 12:18:45 +08:00
@512357301 假设主表(商品表)有 100 万条记录,并且除了 tag 以外,还有 2 个多对多的关系,也需要加入到查询条件中。如果是这种情况,最好还是上倒排索引比较好吧?
yodhcn
2023-03-27 12:20:10 +08:00
@xuelu520 商品表有 100 万条记录,这算大表吗?
aw2350
2023-03-27 12:24:58 +08:00
r_product_tag 不必 一对一吧,这个完全可以用一个数组列解决
notejava
2023-03-27 13:04:00 +08:00
直接 join ,然后从产品设计上,让查询时尽量多带命中索引的筛选条件,比如时间筛选。
lasuar
2023-03-27 13:04:30 +08:00
@yodhcn 不算。千万级表加内存即可。
xuanbg
2023-03-27 22:26:58 +08:00
不要感觉,实际情况是上百万的数据多表关联也能毫秒级查出结果。只要你能够清楚的认识到索引的作用以及优化的第一原则:缩小结果集。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/927430

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX