转置并堆叠一个大的csv文件?

时间:2014-12-16 14:06:49

标签: postgresql csv transpose

我有一个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;

正如我上面提到的,它有效,但是,它很慢。因此,非常感谢建议更快的方式。

0 个答案:

没有答案