Dav*_*vid 7 postgresql etl normalization star-schema fact-table
想象一下PostgreSQL 9.0上具有以下结构的表:
create table raw_fact_table (text varchar(1000));
Run Code Online (Sandbox Code Playgroud)
为了简化起见,我只提到一个文本列,实际上它有十几个.该表有100亿行,每列有很多重复.该表是使用COPY FROM从平面文件(csv)创建的.
为了提高性能,我想转换为以下星型模式结构:
create table dimension_table (id int, text varchar(1000));
Run Code Online (Sandbox Code Playgroud)
然后将事实表替换为如下事实表:
create table fact_table (dimension_table_id int);
Run Code Online (Sandbox Code Playgroud)
我当前的方法是基本上运行以下查询来创建维度表:
Create table dimension_table (id int, text varchar(1000), primary key(id));
Run Code Online (Sandbox Code Playgroud)
然后创建填充我使用的维度表:
insert into dimension_table (select null, text from raw_fact_table group by text);
Run Code Online (Sandbox Code Playgroud)
之后我需要运行以下查询:
select id into fact_table from dimension inner join raw_fact_table on (dimension.text = raw_fact_table.text);
Run Code Online (Sandbox Code Playgroud)
想象一下,通过多次将所有字符串与所有其他字符串进行比较,我获得了可怕的性能.
在MySQL上,我可以在COPY FROM期间运行存储过程.这可以创建字符串的哈希值,并且所有后续字符串比较都是在哈希而不是长原始字符串上完成的.这似乎不可能在PostgreSQL上,我该怎么办?
样本数据将是包含类似内容的CSV文件(我也使用整数和双精度的引号):
"lots and lots of text";"3";"1";"2.4";"lots of text";"blabla"
"sometext";"30";"10";"1.0";"lots of text";"blabla"
"somemoretext";"30";"10";"1.0";"lots of text";"fooooooo"
Run Code Online (Sandbox Code Playgroud)
想象一下,通过多次将所有字符串与所有其他字符串进行比较,我获得了可怕的性能.
当你这样做了一段时间后,你停止想象性能,然后开始测量它."过早优化是万恶之源."
"十亿"对你意味着什么?对我来说,在美国,这意味着1,000,000,000(或1e9).如果你也是这样,你可能会看到1到7太字节的数据.
我当前的方法是基本上运行以下查询来创建维度表:
Create table dimension_table (id int, text varchar(1000), primary key(id));
Run Code Online (Sandbox Code Playgroud)
你如何将100亿行放入一个使用整数作为主键的表中?我们甚至可以说一半的行是重复的.当你这样做时,算法如何工作?
不要想象.先阅读.然后测试.
使用PostgreSQL读取数据仓库.我怀疑这些演示幻灯片会给你一些想法.
另请阅读填充数据库,并考虑要实施哪些建议.
按照"分而治之"的过程,测试一百万(1e6)行.也就是说,不要一次尝试加载一百万; 编写一个程序,将其分解为更小的块.跑
EXPLAIN <sql statement>
Run Code Online (Sandbox Code Playgroud)
您已经说过估计至少有99%的重复行.从广义上讲,有两种方法可以摆脱欺骗
如果你仍然有你加载的文本文件,我会考虑先在数据库外面尝试.这个awk单行将从每个文件输出唯一的行.它相对经济,因为它只对数据进行一次传递.
awk '!arr[$0]++' file_with_dupes > file_without_dupes
Run Code Online (Sandbox Code Playgroud)
如果你真的有99%的傻瓜,那么在这个过程结束时你应该把你的1到7太比特减少到大约50演出.并且,完成此操作后,您还可以对每个唯一行进行编号,并在将其复制到数据仓库之前创建制表符分隔文件.这是另一个单线:
awk '{printf("%d\t%s\n", NR, $0);}' file_without_dupes > tab_delimited_file
Run Code Online (Sandbox Code Playgroud)
如果你必须在Windows下执行此操作,我将使用Cygwin.
如果必须在数据库中执行此操作,我将尽量避免使用生产数据库或生产服务器.但也许我太谨慎了.移动几TB会是一件昂贵的事情.
但我会考试
SELECT DISTINCT ...
Run Code Online (Sandbox Code Playgroud)
在使用GROUP BY之前.我或许可以为你做一些大数据集测试,但本周可能不会.(我通常不会使用太字节大小的文件.这很有趣.如果你可以等.)
只是想问一下: - 是否需要分 1 步或 2 步转换数据?- 我们可以在转换时修改表格吗?
运行更简单的查询可能会提高您的性能(以及执行此操作时的服务器负载)
一种方法是:
或者另一个(可能更好):
| 归档时间: |
|
| 查看次数: |
5740 次 |
| 最近记录: |