Amazon Redshift:找到的表ID不匹配时,如何将`stl_load_errors`行与正确的表名相关联?

时间:2019-04-02 17:53:13

标签: amazon-web-services amazon-s3 amazon-redshift

问题摘要

我使用COPY查询将数据从S3加载到Redshift表t1

99%的时间没有错误,数据已正确加载。因此,我知道加载的表名没有错误。

但是当有错误时,根据我加载的表,我不能总是正确地跟踪在加载此特定表期间发生了哪个错误,因为对于某些已加载的表,例如t1,表标识符{{在tbl中找到的1}}与表stl_load_errors的预期值不符。

我同时在t1stl_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_permCREATE 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

中新错误行中的表ID
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';

令人惊讶的是,此过程对我的某些表而言效果很好,并且我在适用于该表的表和不适用于该表的表之间找不到任何区别。

我在网上还没有找到关于该问题的参考。它需要很多细节,因此也很难搜索。

有什么主意吗?

2 个答案:

答案 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分配分配给一个小表,     然后在表增长时将表更改为偶数分布     更大。分布的变化发生在后台,     秒。 …

  
     

有两种解决方法:

     
      
  1. 在要加载的表上为EVEN,KEY或ALL定义一个显式的DISTSTYLE。我建议此选项主要用于可以   使用KEY diststyle。如果您不使用KEY,则使用AUTO diststyle   将是最有效的。

  2.   
  3. 从stl_load_errors中检索查询ID,从stl_querytext中检索SQL以进行查询,然后按名称查找表   来自pg_class,svv_table_info或stv_tbl_perm。

  4.   

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

请告诉我这是否可以解决您的问题。