PostgreSQL update tbl1 from tbl2 一对多的注意事项(到底匹配哪条)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云原生数据库 PolarDB 分布式版,标准版 2核8GB
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
简介:

标签

PostgreSQL , update from , 一对多


背景

首先A表和B表需要有关联的列, 关联之后A表和B表应该是多对一或者一对一的关系, 一对一的话,很好理解。

如果是一对多会怎么样呢? 任何数据库都会给你一个不确定的答案(与执行计划数据的扫描方法有关)

测试如下 :

sar=> create table a (id int primary key, info text);  
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "a_pkey" for table "a"  
CREATE TABLE  
sar=> create table b (id int, info text);  
CREATE TABLE  
sar=> insert into a select generate_series(1,10),'digoal';  
INSERT 0 10  
sar=> insert into b select generate_series(1,10),'Digoal';  
INSERT 0 10  
sar=> insert into b select generate_series(1,10),'DIGOAL';  
INSERT 0 10  
sar=> select * from a where id=1;  
 id |  info    
----+--------  
  1 | digoal  
(1 row)  
  
sar=> select * from b where id=1;  
 id |  info    
----+--------  
  1 | Digoal  
  1 | DIGOAL  
(2 rows)  

执行如下更新之后, a.id 会等于什么呢? 是Digoal, 还是DIGOAL呢?

看第一个执行计划的结果

b表还没有建索引,使用了nestloop+全表扫描  
  
postgres=# explain update a set info=b.info from b where a.id=b.id and a.id=1;  
                                 QUERY PLAN                                    
-----------------------------------------------------------------------------  
 Update on a  (cost=0.15..28.70 rows=6 width=48)  
   ->  Nested Loop  (cost=0.15..28.70 rows=6 width=48)  
         ->  Index Scan using a_pkey on a  (cost=0.15..2.77 rows=1 width=10)  
               Index Cond: (id = 1)  
         ->  Seq Scan on b  (cost=0.00..25.88 rows=6 width=42)  
               Filter: (id = 1)  
(6 rows)  
  
全表扫描时Digoal这条在前面命中  
  
postgres=# select * from b where id=1 limit 1;  
 id |  info    
----+--------  
  1 | Digoal  
(1 row)  
  
更新拿到了第一条命中的b.info  
  
sar=> update a set info=b.info from b where a.id=b.id and a.id=1;  
UPDATE 1  
sar=> select * from a where id=1;  
 id |  info    
----+--------  
  1 | Digoal  
(1 row)  

看第二个执行计划,使用nestloop+索引扫描

创建一个复合索引,这样可以让索引扫描时, DIGOAL这条记录排到前面  
postgres=# create index idx_b_id on b(id, info);  
CREATE INDEX  
  
  
postgres=# set enable_seqscan=off;  
SET  
  
postgres=# select * from b where id=1 limit 1;  
 id |  info    
----+--------  
  1 | DIGOAL  
(1 row)  
  
现在执行计划,B表使用索引了  
postgres=# explain update a set info=b.info from b where a.id=b.id and a.id=1;  
                                  QUERY PLAN                                     
-------------------------------------------------------------------------------  
 Update on a  (cost=0.29..5.53 rows=1 width=48)  
   ->  Nested Loop  (cost=0.29..5.53 rows=1 width=48)  
         ->  Index Scan using a_pkey on a  (cost=0.15..2.77 rows=1 width=10)  
               Index Cond: (id = 1)  
         ->  Index Scan using idx_b_id on b  (cost=0.14..2.75 rows=1 width=42)  
               Index Cond: (id = 1)  
(6 rows)  
  
现在更新,就变成DIGOAL了。  
postgres=# update a set info=b.info from b where a.id=b.id and a.id=1 returning a.ctid,*;  
  ctid  | id |  info  | id |  info    
--------+----+--------+----+--------  
 (0,11) |  1 | DIGOAL |  1 | DIGOAL  
(1 row)  
  
UPDATE 1  
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
2月前
|
SQL Oracle 关系型数据库
实时计算 Flink版操作报错之往GREENPLUM 6 写数据,用postgresql-42.2.9.jar 报 ON CONFLICT (uuid) DO UPDATE SET 语法有问题。怎么解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
|
8月前
|
关系型数据库 PostgreSQL
postgresql通过select结果进行update
postgresql通过select结果进行update
|
关系型数据库 数据库 数据安全/隐私保护
RDS 5.6 执行update更新报ERROR 1142 (42000)
RDS 5.6 执行update更新报ERROR 1142 (42000)
RDS 5.6 执行update更新报ERROR 1142 (42000)
|
弹性计算 关系型数据库 测试技术
PostgreSQL 分区表如何支持多列唯一约束 - 枚举、hash哈希 分区, 多列唯一, insert into on conflict, update, upsert, merge insert
标签 PostgreSQL , 分区表 , native partition , 唯一 , 非分区键唯一 , 组合唯一 , insert into on conflict , upsert , merge insert 背景 PG 11开始支持HASH分区,10的分区如果要支持hash分区,可以通过枚举绕道实现。 《PostgreSQL 9.x, 10, 11 hash分区表 用法举例
2970 0
|
SQL 关系型数据库 PostgreSQL
PostgreSQL Heap Only Tuple - HOT (降低UPDATE引入的索引写IO放大)
标签 PostgreSQL , Heap Only Tuple , HOT 背景 PostgreSQL目前默认的存储引擎在更新记录时,会在堆内产生一条新版本,旧版本在不需要使用后VACUUM回收,回收旧版本前,需要先回收所有关联这个版本的所有索引POINT。
2489 0
|
关系型数据库 PostgreSQL
PostgreSQL merge insert(upsert/insert into on conflict) 如何区分数据是INSERT还是UPDATE
标签 PostgreSQL , merge insert , upsert , insert into on conflict , 区分 insert update , xmin , xmax 背景 使用insert into on conflict update语法,可以支持UPSERT的功能,但是到底这条SQL是插入的还是更新的呢?如何判断 通过xmax字段的值是否不为0,可以判断,如果是UPDATE,XMAX里面会填充更新事务号。
2091 0
|
SQL 存储 关系型数据库
PostgreSQL 设计优化case - 多对多 转 一对多(数组)
标签 PostgreSQL , 数组 , 多对多 , 一对多 , udf , JOIN 背景 某个系统存储了会员的标签,以及标签的描述信息。业务上需要通过会员ID得到会员的标签,再得到描述信息。 每个会员有若干标签,原来是这么存储的 1、会员标签表,人数5亿左右,每个人平均有几百个标签,1500亿行左右。
2152 0
|
关系型数据库 PostgreSQL 测试技术

相关产品

  • 云原生数据库 PolarDB