4

为了评估我们平台的负载(django + postgresql),我想复制系统中的数据量。创建可以模拟不同类型对象的模拟有点复杂(因为我们有一个非常复杂的数据模型)。有没有办法创建数据库的副本,覆盖未使用的主键和唯一字段并将其与原始字段合并?

4

1 回答 1

1

(一)原理说明

为了清楚地说明原理,本说明假设如下:

  • 每个表都有一个名为“id”的大序列主键列
  • 表上没有唯一约束(主键除外)
  • 外键约束只引用其他表的主键

将以下内容应用于您的数据库架构:

  1. 确保架构中的表之间没有循环依赖关系。如果有,请选择会破坏这种依赖关系的外键约束并删除它们(稍后您将在手动处理受影响的字段后重新创建它们)。
  2. 按拓扑顺序对表进行排序,并按该顺序为每个表执行 (3) 中的脚本
  3. 对于 (2) 中的每个表 <table_schema>.<table_name> 执行:

    /*
    Creating a lookup table which contains ordered pairs (id_old, id_new). 
    For every existing row in table <table_schema>.<table_name>, 
    new row with id = new_id will be created and with all the other fields copied. Nextval of sequence <table_schema>.<table_name>_id_seq is fetched to reserve id for a new row.
    */
    CREATE TABLE _l_<table_schema>_<table_name> AS 
    SELECT id as id_old, nextval('<table_schema>.<table_name>_id_seq') as id_new
    FROM <table_schema>.<table_name>;
    
    /*
    This part is for actual copying of table data with preserving of referential integrity.
    
    Table <table_schema>.<table_name> has the following fields:
    id - primary key
    column1, ..., columnN - fields in a table excluding the foreign keys; N>=0;
    fk1, ..., fkM - foreign keys; M>=0;
    
    _l_<table_schema_fki>_<table_name_fki> (1 <= i <= M) - lookup tables of parent tables. We use LEFT JOIN because foreign key field could be nullable in general case.
    
    */
    INSERT INTO <table_schema>.<table_name> (id, column1, ... , columnN, fk1, ..., fkM)
    SELECT tlookup.id_new, t.column1, ... , t.columnN, tablefk1.id_new, ..., tablefkM.id_new
    FROM <table_schema>_<table_name> t
    INNER JOIN _l_<table_schema>_<table_name> tlookup ON t.id = tlookup.id_old
    LEFT JOIN _l_<table_schema_fk1>_<table_name_fk1> tablefk1 ON t.fk1 = tablefk1.id_old
    ...
    LEFT JOIN _l_<table_schema_fkM>_<table_name_fkM> tablefkM ON t.fkM = tablefkM.id_old;
    
  4. 删除所有查找表。

(二)描述我的实现

  1. 为了检查循环依赖,我查询了传递闭包(https://beagle.whoi.edu/redmine/projects/ibt/wiki/Transitive_closure_in_PostgreSQL
  2. 我实现了拓扑排序功能(从一些博客的 t-sql 移植)。它对自动化非常有用。
  3. 我做了一个代码生成器(在 plpgsql 中实现)。这是一个将 <table_schema> 和 <table_name> 作为输入参数并返回 (I.2) 中显示的该表的文本 (SQL) 的函数。通过按拓扑顺序连接每个表的函数结果,我生成了复制脚本。
  4. 我对脚本进行了手动更改,以满足独特的约束和其他细微差别,而样板脚本没有涵盖这些。
  5. 完毕。准备好在一个事务中执行的脚本。

当我有机会时,我会将我的代码“匿名化”一点并将其放在 github 上并在此处放置一个链接。

于 2013-12-04T13:26:34.000 回答