Postgres快速表分裂

时间:2015-03-11 22:12:36

标签: python postgresql plpgsql

我正在将python代码重写为plpgsql,用于切片表并将表的切片导回到数据库中的不同表中。假设Func(..)是一个返回一些INT的函数 Condition(..., ...)是一些条件表达式。

的Python

  • copy_expert COPY (SELECT *, (Func(B)) FROM TABLE A ORDER BY (SELECT Func(B) FROM B WHERE Condition(A,B)) TO STDOUT到文件
  • 通过写入不同的转储片文件,将生成的表切片到python中的n部分
  • 为每个切片获取一个新游标并运行copy_expert COPY some_table FROM STDIN

PL / PGSQL

  • 运行类似

    的内容
        DECLARE
           ...
           part_name VARCHAR[] = ARRAY[{part_names}];
           prep_stmt VARCHAR[] = ARRAY[{parts}];
        BEGIN 
            FOR i in 1..{parts} LOOP
                prep_stmt[i] := $$ INSERT INTO $$ || part_name[i] || $$
                       ({list_cols}) VALUES ({args}); $$;
            END LOOP;
            FOR row IN (SELECT *, (Func(B)) FROM TABLE A ORDER BY      
                          (SELECT Func(B) FROM B WHERE Condition(A,B))
            LOOP
                chosen_part := 0;
                FOR i IN 1..{parts} LOOP
                    -- choose some part based on Func(B)
                    -- this takes negligible amount of time
                    ... 
                END LOOP;
    
                EXECUTE prep_stmt[part] USING row;
            END LOOP;
        END
    

Python方法更快地执行此任务。我的意思是数量级更快,尽管客户端和数据库是不同的机器。表格 有~16M行,每行有5-7列。

有没有办法让它使用plpgsql更快地运行?

上下文

然后切片将保留在一台机器上,并使用不同的光标和处理器进行处理。切片的原因是进一步处理是CPU而不是IO密集,因为它适用于多边形交集和切片提供了显着的性能优势(至少对于非切片实现)

修改

我真的更喜欢实际回答问题的答案,而不是提出方法是错误的。有时糟糕的设计可以防止轻易改变方法,这可能就是这种情况。问题是为什么python方法更快,以及如何使plpgsql方法更快。

编辑2

是否可以说WRITE TO FILE ...而不是INSERT ...,然后最后批量加载?

编辑3

我想重申一下,我无法避免将切片创建为单独的表格。

我不能为每个切片说CREATE TABLE AS的原因是因为 我是平衡"基于FUNC(B)输出的A中每行的切片。该方法试图模仿min-make-span问题。在CREATE TABLE AS内无法做到类似的事情。

可能的解决方案:

以下是我偶然发现的可能是解决方案的清单,您是否了解其他人?

  • DBLINK扩展插入单独连接中的每个切片?
  • 首先写入未记录的临时表,然后导入切片

1 个答案:

答案 0 :(得分:0)

  

问题是为什么python接近更快以及如何制作   plpgsql的处理速度更快。

这不是由于Python,而是COPYINSERT。使用COPY批量加载 比使用INSERT做同样快。

除此之外,您的查询似乎没有意义:

SELECT *, (Func(B))
FROM TABLE A
ORDER BY (SELECT Func(B) FROM B WHERE Condition(A,B)

多种方式在语法上无效。基于此,很难说出任何话。

只要你住在同一个数据库中,我的第一个想法就是CREATE TABLE AS

CREATE TABLE slice_n AS
SELECT col1, col2, ...
FROM   big_table
ORDER  BY whatever  -- cluster data while being at it
WHERE  whatever;

根据所提供的信息,不能说更多 克雷格收集了一份一般性建议清单: