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

时间:2013-08-22 07:39:03

标签: sql database performance postgresql csv

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

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

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

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

3 个答案:

答案 0 :(得分:6)

fast lane:创建一个匹配CSV文件结构的temporary table(为方便起见,可能使用现有表作为模板)并使用COPY

批量加载

CREATE TEMP TABLE tmp(email text);

COPY tmp FROM 'path/to/file.csv';
ANALYZE tmp;                       -- do that for bigger tables!

假设 CSV中的电子邮件是唯一的,您没有指定。如果不是,那么 make 就是唯一的:

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);

<击>

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

  

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

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

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函数中带EXECUTE的动态SQL。

默认情况下,会话结束时会自动删除临时表 相关回答:
How to bulk insert only new rows in PostreSQL

答案 1 :(得分:2)

只是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来尝试,我会稍后再做

答案 2 :(得分:0)

如果我理解正确,你的CSV文件包含一些字段,包含KEY,用于搜索PostgreSQL表。

我不知道您可以使用哪种编程语言来完成此任务,但一般情况下,您必须解决速度问题:

第一种方法,编程:

  1. 您需要将CSV文件加载到内存中,即使您的CSV每行有500个字节,也只需要100000 * 500 = 50兆字节的RAM
  2. 您需要为CSV的KEY字段构建一些搜索索引 - 例如,在PHP中,您可以构建数组,并将键设置为KEY字段值。在C ++中,您可以创建某种HASH表,这些表由STD lib广泛提供,其他编程语言可以为您提供它们的变体。
  3. PostgreSQL中的表应该由与您的KEY字段匹配的字段编制索引。
  4. 使用你的csv数组,加载到内存中构建查询,如“SELECT * FROM table WHERE key IN(1,2,3,4,5,6,7,8,9)”,其中“1,2, 3,4 ...“ - 是KEY的形式CSV
  5. 的一部分(例如,一百)

    第二种方法,自然sql:

    1. 创建表并将CSV加载到其中
    2. 在字段上创建索引,用于搜索
    3. 在5Millions'表上创建索引
    4. 用户加入以获取链接表数据
    5. 您选择的方式取决于您的实际任务。例如,根据我的经验,我必须创建接口以将价格列表加载到数据库中,并且在实际加载之前,需要显示导入的XLS文件,其中包含有关“当前”和“新”价格的信息,并且因为大尺寸的XLS文件,需要分页,因此,KEY IN(1,2,3,4,5,6)的变体最适合。