我有一个csv文件,包含大约1,500个字段和5-6百万行。这是一个数据集,每个人在1991年ISO第32周以来的某个时间点获得公共福利,每行一行。每个字段代表一周,并且持有与该特定周内收到的特定福利相关的数字。如果个人未收到任何福利,则该字段留空('')。除了每周价值之外,还有许多其他领域(ID,性别,出生日期等)
数据集每季度更新一次,每季度增加一个字段,每个新个人增加一行。
这是数据样本:
y_9132,y_9133,y_9134,...,y_1443,id,sex,dateofbirth
891,891,891,...,110,1000456,1,'1978/01/16'
110,112,112,...,997,2000789,0,'1945/09/28'
我正在尝试将数据转换为表格格式,以便可以使用带有comlumn存储或类似功能的PostgreSQL进行分析(Amazon Redshift是可能的)。
以“y_”开头的字段表示收到的公共福利的年份和周数。在表格格式中,字段名称应转换为行号或日期,从1991年ISO第32周(1991/08/05)的星期一开始。
我正在尝试将csv文件转换为的单元格数据集如下所示: (周只是一个序列号,从'1991/08/05'开始时为1)
week,benefit,ID
1,891,1000456
2,891,1000456
3,891,1000456
...
1211,110,1000456
1,110,2000789
2,112,2000789
3,112,2000789
...
1211,997,2000789
我在PostgreSQL中编写了一个可以正常工作的函数,但它非常慢。整个转换需要15h。我尝试过使用带有SSD和8GB RAM的笔记本电脑。我也在具有30GB内存的Amazon RDS实例上尝试过它。仍然很慢。 PostgreSQL函数将csv拆分为块。我已经尝试了一点和100K行pr。批次似乎最快(是的,快15小时)。
要说清楚,我并不是特别想用PostgreSQL寻找解决方案。什么都行。事实上,我不确定为什么我甚至会使用数据库来进行此操作。
那就是说,这是我在PostgreSQL中的函数:
第一个功能:我将部分csv文件加载到名为part_grund的表中。我只使用每周数据和ID加载字段。
CREATE OR REPLACE FUNCTION DREAMLOAD_PART(OUT result text) AS
$BODY$
BEGIN
EXECUTE 'DROP TABLE IF EXISTS part_grund;
CREATE UNLOGGED TABLE part_grund
(id int, raw_data text[],rn int[]);
INSERT INTO part_grund
SELECT raw_data[1300]::int
,raw_data[1:1211]
,rn
FROM grund_no_headers
cross join
(
SELECT ARRAY(
WITH RECURSIVE t(n) AS
(
VALUES (1)
UNION ALL
SELECT n+1 FROM t WHERE n < 1211
)
SELECT n FROM t
) AS rn) AS rn;
CREATE INDEX idx_id on part_grund (id);';
END;
$BODY$
LANGUAGE plpgsql;
第二个功能:这里,使用不需要的函数转换数据。
CREATE OR REPLACE FUNCTION DREAMLOAD(startint int, batch_size int, OUT result text) AS
$BODY$
DECLARE
i integer := startint;
e integer := startint + batch_size;
endint integer;
BEGIN
endint := (SELECT MAX(ID) FROM part_grund) + batch_size;
EXECUTE 'DROP TABLE IF EXISTS BENEFIT;
CREATE UNLOGGED TABLE BENEFIT (
ID integer
,benefit smallint
,Week smallint
);';
WHILE e <= endint LOOP
EXECUTE 'INSERT INTO BENEFIT
SELECT ID
,unnest(raw_data) AS benefit
,unnest(rn) AS week
FROM part_grund
WHERE ID between ' || i || ' and ' || e-1 ||';';
i=i+batch_size;
e=e+batch_size;
END LOOP;
END;
$BODY$
LANGUAGE plpgsql;
正如我上面提到的,它有效,但是,它很慢。因此,非常感谢建议更快的方式。