一、背景

在工作中,可能会遇到将表从一个表空间移动另一个表空间。例如

* 对数据进行冷处理
* 表空间所在的磁盘空间不足
* 建表时分配错了表空间

以上等等,可能需要你将一个表移动表空间。

二、表空间介绍

PostgreSQL的表空间

三、移动数据文件方法

我们先打造下环境;创建两个表空间

postgres=# CREATE TABLESPACE tsp01 OWNER lottu LOCATION '/data/pg6000/tsp01';
CREATE TABLESPACE
postgres=# CREATE TABLESPACE tsp02 OWNER lottu LOCATION '/data/pg6000/tsp02';
CREATE TABLESPACE

查看数据库默认表空间

postgres=# \c lottu lottu
You are now connected to database "lottu" as user "lottu".
lottu=> select d.datname,p.spcname from pg_database d, pg_tablespace p where d.datname='lottu' and p.oid = d.dattablespace;
 datname |  spcname   
---------+------------
 lottu   | pg_default
(1 row)

接下来我们在表空间tsp01建表tbl_lottu

lottu=> create table tbl_lottu(id int primary key, info text) TABLESPACE tsp01;
CREATE TABLE
lottu=> insert into tbl_lottu select generate_series(1,1000) ,md5(random()::text);
INSERT 0 1000
lottu=> \d tbl_lottu
              Table "lottu.tbl_lottu"
 Column |  Type   | Collation | Nullable | Default 
--------+---------+-----------+----------+---------
 id     | integer |           | not null | 
 info   | text    |           |          | 
Indexes:
    "tbl_lottu_pkey" PRIMARY KEY, btree (id)
Tablespace: "tsp01"

而表tbl_lottu数据文件的位置

lottu=> select pg_relation_filepath('tbl_lottu');
pg_relation_filepath
---------------------------------------------
pg_tblspc/90618/PG_12_201909212/24750/90620
(1 row)

3.1、alter table

将表从一个表空间移到另一个表空间

lottu=> ALTER TABLE tbl_lottu SET TABLESPACE tsp02;
ALTER TABLE

我们再查看表;已经成功移动表空间tsp02

lottu=> \d tbl_lottu 
              Table "lottu.tbl_lottu"
 Column |  Type   | Collation | Nullable | Default 
--------+---------+-----------+----------+---------
 id     | integer |           | not null | 
 info   | text    |           |          | 
Indexes:
    "tbl_lottu_pkey" PRIMARY KEY, btree (id)
Tablespace: "tsp02" lottu=> select pg_relation_filepath('tbl_lottu');
            pg_relation_filepath             
---------------------------------------------
 pg_tblspc/90619/PG_12_201909212/24750/90629
(1 row)

不足之处:在alter table这个过程中是锁表的;若是大表;执行时间久,在这个时间内表在dml操作一直处在等待。那有没有不锁表,或者锁表的时间极短的方法呢?

3.2、create + copy

我们想想,在做表的移动表空间操作步骤可以理解是,

新建一个表在tsp02中,再把数据copy过来,再用新表替换旧表。该方式操作太复杂了,同时也不能保证数据的完整性。在确保在这段时间内不对表进行任何操作;可以试下。

3.3、pg_repack

在生产环境处理表膨胀,我们会考虑用pg_repack来取代vacuum full,因为它在处理表膨胀的过程中可以避免表被长期锁定。pg_repack工作原理:创建一个新表,将数据从旧表移动到新表。为了避免表被独占锁定,创建了一个额外的日志表来记录原始表的改动,还添加了一个把INSERT / UPDATE / DELETE操作记录到日志表的触发器。当原始表中的数据全部导入到新表中,索引重建完毕,日志表的改动全部完成,pg_repack会连同新索引,用新表替换旧表,并将原旧表Drop掉。整个过程非常简单,非常可靠。同时它还支持在不同表空间迁移表和索引

我们开始实际操作下:

第一步:先创建表tbl_repack;

lottu=# create table tbl_repack(id int primary key, info text) TABLESPACE tsp01;
CREATE TABLE
lottu=# insert into tbl_repack select generate_series(1,1000000) ,md5(random()::text);
INSERT 0 1000000
lottu=# select pg_relation_filepath('tbl_repack');
            pg_relation_filepath             
---------------------------------------------
 pg_tblspc/90618/PG_12_201909212/24750/90681
(1 row)

第二步:执行pg_repack

[postgres@lottu ~]$ pg_repack -t lottu.tbl_repack -s tsp02 -j 2 -d lottu -U lottu
NOTICE: Setting up workers.conns
INFO: repacking table "lottu.tbl_repack"

执行的同时;我们对表tbl_repack执行delete操作;实验是否堵塞dml操作

lottu=# delete from tbl_repack where id < 100;
DELETE 99

第三步:查看是否移动成功

lottu=# select pg_relation_filepath('tbl_repack');
            pg_relation_filepath             
---------------------------------------------
 pg_tblspc/90619/PG_12_201909212/24750/90704
(1 row)
lottu=# \d tbl_repack;
             Table "lottu.tbl_repack"
 Column |  Type   | Collation | Nullable | Default 
--------+---------+-----------+----------+---------
 id     | integer |           | not null | 
 info   | text    |           |          | 
Indexes:
    "tbl_repack_pkey" PRIMARY KEY, btree (id)
Tablespace: "tsp02"
lottu=# select count(1) from tbl_repack ;
 count  
--------
 999901
(1 row)

限制之处:

  1. 执行pg_repack操作需要超级用户
[postgres@lottu ~]$ pg_repack -t tbl_repack -s tsp02 -j 2 -d lottu -U lottu
NOTICE: Setting up workers.conns
ERROR: pg_repack failed with error: You must be a superuser to use pg_repack
  1. 移动的表需要有主键或者唯一索引;这个取决于pg_repack实现原理;大家可以去查看官方文档
[postgres@lottu ~]$ pg_repack -t lottu.tbl_repack -s tsp02 -j 2 -d lottu -U lottu
NOTICE: Setting up workers.conns
WARNING: relation "lottu.tbl_repack" must have a primary key or not-null unique keys

最新文章

  1. 常用的一些复杂SQL语句
  2. 分享一个 C# Winfrom 下的 OutlookBar 控件的使用
  3. Java面试题汇总(一)
  4. Javascript添加事件的addEventListener()及attachEvent()区别分析,事件委托
  5. JavaScript —— attachEvent 方法的使用
  6. 【剑指offer】不用加减乘除做加法
  7. 对HGE游戏引擎的一次封装
  8. tomcat 修改端口(Java之负基础实战)
  9. js坚持不懈之16:使用js向HTML元素分配事件
  10. centos6删除nginx
  11. mysql初始化提示安装perl
  12. 20155212 2016-2017-2 《Java程序设计》第6周学习总结
  13. Redis 学习笔记1
  14. spring JPA分页排序条件查询
  15. 浅析 golang module
  16. 【左偏树】【P3261】 [JLOI2015]城池攻占
  17. Python3量化技术常用插件
  18. hey-cli初使用
  19. iOS开发神器InjectionIII
  20. Bootstrap 栅格系统初识

热门文章

  1. CF R 632 div2 1333F Kate and imperfection
  2. windows:shellcode 远程线程hook/注入(三)
  3. Python稳居编程语言榜首,看完这篇总结,你就明白为什么要学它了
  4. 009_go语言中的slices分片
  5. GIT pull 如何解决 fatal: refusing to merge unrelated histories
  6. JS 鼠标放上去滑出内容案例
  7. 【工具】之002-Mac下常用工具
  8. IndexFlatL2、IndexIVFFlat、IndexIVFPQ三种索引方式示例
  9. Deep Learning-Based Document Modeling for Personality Detection from Text 阅读笔记
  10. C#图解教程(第四版)—02—类的基本概念