我有一个 Postgre SQL 数据库表,其中包含超过 500 万个条目。还有一个包含 100,000 个条目的 CSV 文件。
我需要运行查询以从数据库中获取与 CSV 文件数据相关的数据。
但是根据大家的理解和我自己的经验,这种查询需要很长时间才能完成。(根据我的猜测,超过 6 小时)
因此,根据最新的发现和工具,我们是否有更好、更快的解决方案来执行相同的任务?
我有一个 Postgre SQL 数据库表,其中包含超过 500 万个条目。还有一个包含 100,000 个条目的 CSV 文件。
我需要运行查询以从数据库中获取与 CSV 文件数据相关的数据。
但是根据大家的理解和我自己的经验,这种查询需要很长时间才能完成。(根据我的猜测,超过 6 小时)
因此,根据最新的发现和工具,我们是否有更好、更快的解决方案来执行相同的任务?
快速通道:创建一个与 CSV 文件结构匹配的临时表(为方便起见,可能使用现有表作为模板)并使用COPY
:
CREATE TEMP TABLE tmp(email text);
COPY tmp FROM 'path/to/file.csv';
ANALYZE tmp; -- do that for bigger tables!
我假设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;
对于您的特定情况,电子邮件的唯一索引是有序的。在加载和清理数据后创建索引效率更高。这样COPY
,如果应该有欺骗,您还可以防止以独特的违规行为进行救助:
CREATE UNIQUE INDEX tmp_email_idx ON tmp (email);
再想一想,如果您所做的只是更新大表,那么您根本不需要临时表上的索引。它将被顺序读取。
是的,数据库表是使用主键索引的。
在这种情况下唯一相关的索引:
CREATE INDEX tbl_email_idx ON tbl (email);
CREATE UNIQUE INDEX ...
如果可能的话,做到这一点。
要更新您的表格,如您稍后评论中所述:
UPDATE tbl t
SET ...
FROM tmp
WHERE t.email = tmp.email;
所有这些都可以很容易地封装到 plpgsql 或 sql 函数中。
请注意,如果要参数化文件名,则COPY
需要在 plpgsql 函数中使用动态 SQL 。EXECUTE
默认情况下,临时表会在会话结束时自动删除。
相关答案:
如何在 PostreSQL 中仅批量插入新行
只是 Erwin 答案的一个小补充 - 如果您只想检查 csv 文件中的电子邮件,代码可能是这样的:
create temp table tmp_emails (email text primary key);
copy tmp_emails from 'path/emails.csv';
analyze tmp_emails;
update <your table> set
...
from <your table> as d
where exists (select * from tmp_emails as e where e.email = d.email);
我认为可能有可能创建读取您的 csv 并调用它的表返回函数:
update <your table> set
...
from <your table> as d
where exists (select * from csv_func('path/emails.csv') as e where e.email = d.email);
但是我这里没有安装postgresql可以试试,以后再做
如果我对您的理解正确,您的 CSV 文件包含一些字段,其中包含 KEY,用于搜索您的 PostgreSQL 表。
我不知道您可以使用哪种编程语言来完成此任务,但总的来说,您必须解决速度问题:
第一种方法,编程:
第二种方法,自然sql:
您将选择的方式取决于您的实际任务。例如,根据我的经验,我必须制作接口来将价格表加载到数据库中,并且在实际加载之前,需要显示导入的 XLS 文件,其中包含有关“当前”和“新”价格的信息,并且,因为大尺寸的 XLS 文件,在哪里需要分页,所以,带有 KEY IN (1,2,3,4,5,6) 的变体最适合。