如何从SQL查询中获得快速结果

inc*_*kka 2 sql database csv postgresql performance

我有一个Postgre SQL数据库表,其中包含超过500万条目.还有一个包含100,000个条目的CSV文件.

我需要运行一个查询来从DB获取与CSV文件数据相关的数据.

然而,根据每个人的理解和我自己的经验,这种查询需要很长时间才能完成.(超过6个小时,根据我的猜测)

因此,根据最新的研究结果和工具,我们是否有更好,更快的解决方案来执行同样的任务?

Erw*_*ter 6

快速通道:创建一个临时表(可能使用现有表作为模板,方便),并使用相匹配的CSV文件的结构COPY:

批量装载

CREATE TEMP TABLE tmp(email text);

COPY tmp FROM 'path/to/file.csv';
ANALYZE tmp;                       -- do that for bigger tables!
Run Code Online (Sandbox Code Playgroud)

假设 CSV中的电子邮件是唯一的,您没有指定.如果不是,使他们独特的:

CREATE TEMP TABLE tmp0
SELECT DISTINCT email
FROM   tmp
ORDER  BY email;  -- ORDER BY cheap in combination with DISTINCT ..
                  -- .. may or may not improve performance additionally.

DROP TABLE tmp;
ALTER TABLE tmp0 RENAME TO tmp;
Run Code Online (Sandbox Code Playgroud)

指数

对于您的特定情况,电子邮件中的唯一索引是有序的.加载和清理数据创建索引要高效得多.通过这种方式,COPY如果存在欺骗行为,您还可以防止以独特的违规行为挽救:

CREATE UNIQUE INDEX tmp_email_idx ON tmp (email);
Run Code Online (Sandbox Code Playgroud)

第二个想法,如果您只是更新大表,则根本不需要临时表上的索引.它将按顺序读取.

是DB表使用主键编制索引.

在这种情况下唯一相关的索引:

CREATE INDEX tbl_email_idx ON tbl (email);
Run Code Online (Sandbox Code Playgroud)

作出这样CREATE UNIQUE INDEX ...如果可能的话.

更新

要更新您的表格,请在以后的评论中详细说明:

UPDATE tbl t
SET    ...
FROM   tmp 
WHERE  t.email = tmp.email;
Run Code Online (Sandbox Code Playgroud)

所有这些都可以很容易地包装到plpgsql或sql函数中.
请注意,如果要参数化文件名,则COPY需要EXECUTE在plpgsql函数中使用动态SQL .

默认情况下,会话结束时会自动删除临时表.
相关回答:
如何批量插入PostreSQL中的新行