繁体   English   中英

如何有效地将树状数据结构插入 postgres

[英]How to efficiently insert tree-like data structure into postgres

本质上,我想用 Postgres 有效地将树状数据结构存储在表中。 每行都有一个 ID(插入时自动生成)、一个父 ID(引用同一个表中的另一行,可能为 null)和一些额外的元数据。 所有这些数据都是一次进入的,所以我试图尽可能有效地一次存储它们。

我目前的想法是按它们所在的树的哪个级别对所有数据进行分组,并一次批量插入一个级别。 这样我就可以使用从上一级插入中生成的 ID 来设置父 ID。 这样,批次的数量与树中的层数相关。

这可能“足够好”,但我想知道是否有更好的方法来做这种事情? 当我已经在 memory 中拥有整个数据树并且结构正确时,这对我来说似乎仍然有很多来回和不必要的逻辑。

让我展示一下如果我有一些关于谁是谁的孩子记录的信息,我会怎么做。 就我而言,我使用一个包含来自源的信息的临时表。 这些记录有一个基于字符的主键id和一个自引用、可为空的外键boss_id

开始:

-- the input table with "business identifiers".
DROP TABLE IF EXISTS rec_input;
CREATE TABLE rec_input (
  id         CHAR(4)
, first_name VARCHAR(32)
, last_name  VARCHAR(32)
, boss_id    CHAR(4)
) 
;

-- some data for it ...
INSERT INTO rec_input(id,first_name,last_name,boss_id)
          SELECT 'A01','Arthur','Dent'           ,NULL
UNION ALL SELECT 'A02','Ford','Prefect'          ,'A01'
UNION ALL SELECT 'A03','Zaphod','Beeblebrox'     ,'A01'
UNION ALL SELECT 'A04','Tricia','McMillan'       ,'A01'
UNION ALL SELECT 'A05','Gag','Halfrunt'          ,'A02'
UNION ALL SELECT 'A06','Prostetnic Vogon','Jeltz','A02'
UNION ALL SELECT 'A07','Lionel','Prosser'        ,'A04'
UNION ALL SELECT 'A08','Benji','Mouse'           ,'A04'
UNION ALL SELECT 'A09','Frankie','Mouse'         ,'A04'
UNION ALL SELECT 'A10','Svlad','Cjelli'          ,'A03'
;

-- create a lookup table. The surrogate key is created here.
DROP TABLE IF EXISTS lookup_help;
CREATE TABLE lookup_help (
  sk SERIAL NOT NULL -- < here is the surrogate auto increment key
, id CHAR(3)
);

-- fill the lookup table
INSERT INTO lookup_help(id) 
SELECT id FROM rec_input;
-- test query
SELECT * FROM lookup_help;

-- this is the target table, with auto increment
-- and matching surrogate foreign key.
DROP TABLE IF EXISTS rec;
CREATE TABLE rec (
  sk         INTEGER     NOT NULL -- surrogate key
, id         CHAR(4).  -- "business id"
, first_name VARCHAR(32)
, last_name  VARCHAR(32)
, boss_id    CHAR(4).  -- "business foreign key", not needed really
, boss_sk    INTEGER.  -- internal foreign key
) 
;

INSERT INTO rec
SELECT
  l.sk -- from lookup table, inner joined
, i.id -- from input table
, i.first_name
, i.last_name
, i.boss_id
, b.sk -- from lookup table, left outer joined
FROM rec_input i
JOIN lookup_help l USING(id) -- for the main sk
LEFT JOIN lookup_help b ON i.boss_id=b.id -- for the foreign sk
;
-- test query
SELECT * FROM rec;

-- out  sk |  id  |    first_name    | last_name  | boss_id | boss_sk 
-- out ----+------+------------------+------------+---------+---------
-- out   2 | A02  | Ford             | Prefect    | A01     |       1
-- out   3 | A03  | Zaphod           | Beeblebrox | A01     |       1
-- out   4 | A04  | Tricia           | McMillan   | A01     |       1
-- out   6 | A06  | Prostetnic Vogon | Jeltz      | A02     |       2
-- out   5 | A05  | Gag              | Halfrunt   | A02     |       2
-- out  10 | A10  | Svlad            | Cjelli     | A03     |       3
-- out   7 | A07  | Lionel           | Prosser    | A04     |       4
-- out   8 | A08  | Benji            | Mouse      | A04     |       4
-- out   9 | A09  | Frankie          | Mouse      | A04     |       4
-- out   1 | A01  | Arthur           | Dent       |         |        
-- out (10 rows)

也许对于您的用例,您现在可以尝试 NoSql,查询此类数据会更加高效和快捷。 也许试一试。

对于开发,您可以选择 Apache CouchDB、redis 等。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM