博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
PostgreSQL update tbl1 from tbl2 一对多的注意事项(到底匹配哪条)
阅读量:5981 次
发布时间:2019-06-20

本文共 2853 字,大约阅读时间需要 9 分钟。

标签

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

转载地址:http://ihlox.baihongyu.com/

你可能感兴趣的文章
Jquery 校验文本框只能输入负数、小数、整数
查看>>
关于固态硬盘SSD的4K对齐
查看>>
fanc委托在项目中使用
查看>>
C# FileStream 按大小分段读取文本内容
查看>>
WGS84,GCJ02, BD09坐标转换
查看>>
如何给网页标题栏上添加图标(favicon.ico)(转)
查看>>
[转载] Linux架构
查看>>
mysql授权
查看>>
Ubuntu下SSH设置
查看>>
IOS-小项目( 网络部分 简单实现)
查看>>
C/C++基本数据类型
查看>>
C++第八章习题
查看>>
multiset || 线段树 HDOJ 4302 Holedox Eating
查看>>
POJ2115:C Looooops——题解
查看>>
Spring-boot+Mybatis+Maven+MySql搭建实例
查看>>
最基本的js与css 控制弹出层效果
查看>>
第12章线程控制总结
查看>>
网络对抗技术实验一
查看>>
mysql命令大全
查看>>
KVO
查看>>