提到多对多关系,第一个反应是 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=苹果,橘子
),只用数据库该怎样实现?JOIN
在一起?感觉查询效率会很低。t_product
新增一冗余列 tags (character verying)
,并在该列上建立 PostgreSQL
的 GIN
索引。这种方式顺便还可以通过分词将单个标签的字符串拆分成多个关键字,更容易搜索。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[]) |
不知道 PostgreSQL 对 integer[]
类型字段的索引机制是怎样的?
1
liprais 2023-03-27 10:38:21 +08:00
谁告诉你多表 join 效率低的?
|
2
liuzhen 2023-03-27 10:49:16 +08:00
脱离数据量说效率是耍流氓;大表 join 效率是低的,可以考虑拆 sql 多次查询,小表 join 就完事了
|
4
CNife 2023-03-27 10:54:06 +08:00
建议自己实验一下,用 EXPLAIN ANALYZE 看看如何处理和代价如何
|
5
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 更新频率较低可以放缓存里 |
6
iwishing 2023-03-27 11:19:30 +08:00
有个问题,为啥多标签是交集而不是并集?搜索我一般喜欢并集,筛选喜欢交集。
|
7
zoharSoul 2023-03-27 11:23:31 +08:00
es 直接拍平了
|
9
yodhcn OP @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 |
10
TWorldIsNButThis 2023-03-27 11:54:00 +08:00
这就是 es 出现的原因
|
11
xuelu520 2023-03-27 12:01:16 +08:00
--直接将 3 张表 JOIN 在一起?感觉查询效率会很低。
这个思维就是错的。 正常情况 JOIN 查就是了,大表 JOIN 就需要 es 了。 |
12
512357301 2023-03-27 12:11:17 +08:00 via Android
效率低那是阿里巴巴提出来的吧,好像他们有个 MySQL 开发规范,不过如楼上所说,脱离数据量谈效率就是耍流氓,你一个配置表几千几万条数据,谈效率低,啧啧啧。
join 效率低说的是百万千万量级的时候效率低,这也不是 join 的锅,这是 MySQL 的锅 |
13
yodhcn OP @512357301 假设主表(商品表)有 100 万条记录,并且除了 tag 以外,还有 2 个多对多的关系,也需要加入到查询条件中。如果是这种情况,最好还是上倒排索引比较好吧?
|
15
aw2350 2023-03-27 12:24:58 +08:00
r_product_tag 不必 一对一吧,这个完全可以用一个数组列解决
|
16
notejava 2023-03-27 13:04:00 +08:00
直接 join ,然后从产品设计上,让查询时尽量多带命中索引的筛选条件,比如时间筛选。
|
18
xuanbg 2023-03-27 22:26:58 +08:00
不要感觉,实际情况是上百万的数据多表关联也能毫秒级查出结果。只要你能够清楚的认识到索引的作用以及优化的第一原则:缩小结果集。
|