繁体   English   中英

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

[英]How to get fast result from a SQL query

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

我需要运行一个查询来从DB获取与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);
 
  

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

是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。

默认情况下,会话结束时会自动删除临时表。
相关回答:
如何批量插入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表。

我不知道你可以用什么编程语言完成这项任务,但是,一般来说,你必须解决速度问题:

第一种方法,编程:

  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的一部分(例如,一百个)

第二种方法,自然sql:

  1. 创建表并将CSV加载到其中
  2. 在字段上创建索引,用于搜索
  3. 在5Millions表上创建索引
  4. 用户JOIN获取链接表数据

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM