我使用COPY查询将数据从S3加载到Redshift表t1
。
99%的时间没有错误,数据已正确加载。因此,我知道加载的表名没有错误。
但是当有错误时,根据我加载的表,我不能总是正确地跟踪在加载此特定表期间发生了哪个错误,因为对于某些已加载的表,例如t1
,表标识符{{在tbl
中找到的1}}与表stl_load_errors
的预期值不符。
我同时在t1
和stl_load_errors
上过滤filename
,因为可能将同一个S3文件加载到不同的表中,所以仅对文件名进行过滤不是检查是否安全的方法。在一个特定的COPY查询期间出现错误。
已加载的表名未出现在此表中,相反,我们在列tbl
中获得了整数标识符1234567
。我们必须与另一个包含名称和标识符的表tbl
联接,以获取名称。 Redshift文档中显示了此“技巧”。
对于某些表,例如stv_tbl_perm
,在使用t1
后在stl_load_errors
中可能出现的错误行在COPY t1 ...
列中将具有一个标识符1234567
,与tbl
中找不到的任何内容相对应。好像它是临时表的标识符。
然后,当我在stv_tbl_perm
中查找stv_tbl_perm
时,确实在"name"='t1'
列中找到了一个标识符10111213
,但这不是我在{{1 }}。
让我更加困惑的是,我的文件和表错误过滤方法对于某些Redshift表来说非常完美,发现的id
是预期的,它与正确的{{1}相匹配}在stl_load_errors
中。
为什么我对表的COPY遍历某个表而不是其他表的临时表?
我试图尽可能简化共享过程,并设法重现我的问题,如下所述。
1。创建表,插入行,使其不为空并进行检查。
id
2。创建一个故意输入错误的S3文件
我在“ id”列中写了一个字符,因此在加载期间会导致类型错误。
name
请确保将stv_tbl_perm
,CREATE TABLE IF NOT EXISTS public.t1
(
id INTEGER,
name VARCHAR(36),
price NUMERIC(6,2)
);
insert into t1 VALUES (1, 'paul', 10.50);
select * from t1;
和unload ('select ''a'' as "id", ''pierre'' as "name", 2.50 as "price"')
to 's3://my-bucket/redshift-load-error-table-id/unload/t1_'
iam_role 'arn:aws:iam::1111111111:role/my-user'
parallel off
delimiter ',';
替换为您自己的值。
3。使用COPY将此文件加载到表中
my-bucket
查询失败,在表1111111111
中生成一行。
4。检查my-user
COPY t1
from 's3://my-bucket/redshift-load-error-table-id/unload/t1_000'
iam_role 'arn:aws:iam::1111111111:role/my-user'
CSV;
我们找到与文件相对应的行,并将表标识符保留在stl_load_errors
列中,比方说stl_load_errors
(您会得到一些不同的东西)。
5。在SELECT *
FROM stl_load_errors
where trim(filename) = 's3://my-bucket/redshift-load-error-table-id/unload/t1_000';
中查找此表标识符以获取表名
tbl
这不返回任何内容,找到的标识符与"tbl" = 1234567
中列出的任何永久表都不对应。
好像它是临时表的标识符。
6。查找我们加载到的表的预期标识符
stv_tbl_perm
这将返回select *
from stv_tbl_perm
where id='1234567';
(您会得到一些不同的结果),这是我应该在表stv_tbl_perm
的{{1}}列中获得的标识符。
如果我尝试另一个带错误的COPY,则错误表中将出现另一行,并带有另一个不同于先前两个标识符的标识符。这也表明它可能是临时表的标识符。
因此,我无法为应用COPY查询的特定表过滤select *
from stv_tbl_perm
where name='t1';
。
令人惊讶的是,此过程对我的某些表而言效果很好,并且我在适用于该表的表和不适用于该表的表之间找不到任何区别。
我在网上还没有找到关于该问题的参考。它需要很多细节,因此也很难搜索。
有什么主意吗?
答案 0 :(得分:1)
由于我在问题所在的AWS开发人员论坛上的AWS工程师最近使用了Redshift功能,因此将其识别为实际的Redshift问题。
@ joeharris76-AWS:
好的,谢谢您引起我们的注意。我们已经确定了 此问题的来源,并将调查修复方法。固定后 注意将出现在我们的常规维护公告中 论坛顶部。
这与我们引入的自动DISTSTYLE功能有关 最近。对于当前为ALL的DISTSTYLE AUTO表,我们加载 新数据放入临时表,然后检查是否添加了新行 要求将表从ALL转换为EVEN。 https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html
DISTSTYLE {自动|偶数KEY | ALL}默认为AUTO。 …自动: Amazon Redshift会根据 表数据。例如,如果指定了AUTO分配样式, Amazon Redshift最初将ALL分配分配给一个小表, 然后在表增长时将表更改为偶数分布 更大。分布的变化发生在后台, 秒。 …
有两种解决方法:
在要加载的表上为EVEN,KEY或ALL定义一个显式的DISTSTYLE。我建议此选项主要用于可以 使用KEY diststyle。如果您不使用KEY,则使用AUTO diststyle 将是最有效的。
从stl_load_errors中检索查询ID,从stl_querytext中检索SQL以进行查询,然后按名称查找表 来自pg_class,svv_table_info或stv_tbl_perm。
https://forums.aws.amazon.com/thread.jspa?messageID=897976
在我的小复制中指定DISTSTYLE
确实解决了问题,并且我将对生产表应用相同的解决方案,因为它们似乎符合EVEN样式(亿万行,无联接)。
因此,在我的复制情况下,我在表创建中添加了一行:
CREATE TABLE IF NOT EXISTS public.t1
(
id INTEGER,
name VARCHAR(36),
price NUMERIC(6,2)
)
DISTSTYLE EVEN;
现在stl_load_errors
中找到的表标识符确实与stv_tbl_perm
中的期望表相对应。
我还通过查询stl_querytext
表来测试了该方法,并且在我的复制情况下也可以使用,但是我发现解析字符串来查找表名不是很干净也不有效。在内部,因此我会坚持在当前情况下添加DISTSTYLE EVEN
。
答案 1 :(得分:0)
使用stv_tbl_perm
代替pg_class
。您可以将Postgres目录表中的oid
(数据库对象ID)列用作连接列
select c.relname table_name, s.*
from stl_load_errors s, pg_class c
where c.oid = s.tbl
and c.relname = '<your table name>'
更多信息
https://docs.aws.amazon.com/redshift/latest/dg/c_join_PG.html
请告诉我这是否可以解决您的问题。