【问题标题】:Loading JSON data to AWS Redshift results in NULL values将 JSON 数据加载到 AWS Redshift 会导致 NULL 值
【发布时间】:2015-09-16 15:34:52
【问题描述】:

我正在尝试执行加载/复制操作以将数据从 S3 存储桶中的 JSON 文件直接导入 Redshift。 COPY 操作成功,并且在 COPY 之后,表有正确的行数/记录数,但每条记录都是 NULL!

加载需要预期的时间,COPY 命令返回 OK,Redshift 控制台报告成功并且没有错误...但是如果我从表中执行简单查询,它只会返回 NULL 值。

JSON 非常简单 + 扁平化,并且格式正确(根据我在这里找到的示例:http://docs.aws.amazon.com/redshift/latest/dg/r_COPY_command_examples.html

基本上每行一行,格式如下:

{ "col1": "val1", "col2": "val2", ... }
{ "col1": "val1", "col2": "val2", ... }
{ "col1": "val1", "col2": "val2", ... }

我尝试过一些事情,比如根据 JSON 对象中的值和数据类型重写架构,以及从未压缩的文件中复制。我想也许 JSON 在加载时没有被正确解析,但如果无法解析对象,它应该会引发错误。

我的 COPY 命令如下所示:

copy events from 's3://mybucket/json/prefix' 
with credentials 'aws_access_key_id=xxx;aws_secret_access_key=xxx'
json 'auto' gzip;

任何指导将不胜感激!谢谢。

【问题讨论】:

    标签: amazon-web-services amazon-redshift


    【解决方案1】:

    所以我发现了原因 - 从我在原始帖子中提供的描述中看不到这一点。

    当您在 Redshift 中创建表时,列名将转换为小写。 执行 COPY 操作时,列名区分大小写。

    我一直在尝试加载的输入数据使用 camelCase 作为列名,因此当我执行 COPY 时,这些列与定义的架构不匹配(现在使用所有小写的列名)

    不过,该操作不会引发错误。它只是在所有不匹配的列中留下 NULL(在这种情况下,所有列)

    希望这可以帮助人们避免同样的困惑!

    【讨论】:

    • 这是我在挖掘后发现的相同问题。但我想知道是否有文档/解决方案可以告诉它忽略大小写或转换它。对于我正在处理的音量,更改 json 密钥格式将是一件非常痛苦的事情。编辑:没关系,你必须使用 jsonPaths 解决方案
    • 我偶然发现了这个错误,因为 NOT NULL 列说我的 JSON 没有任何价值,这是错误的。一个快速的谷歌搜索在这里登陆。我会说接受这个答案,因为它对我正在研究的管道的一个关键组成部分有很大帮助。我将看到如何通过票证将请求转发给亚马逊团队以支持不区分大小写的列名(无论如何都是 SQL 标准)。
    • 我可以确认也是这种情况。亚马逊在他们的文档中根本没有提及案例以及对 Redshift“自动”副本的巨大遗漏,真是太可惜了。本质上,如果您的 JSON 属性名称使用小写字符以外的任何字符,则必须使用 JSONPaths 文件!
    • 现在有一个选项可以在将 JSON 数据从 s3 加载到 Redshift 时忽略大小写
    【解决方案2】:

    对于 JSON 数据对象不直接对应于列名的情况,您可以使用 JSONPaths 文件将 JSON 元素映射到 TimZ 提到的列和描述 here

    【讨论】:

      【解决方案3】:

      COPY 将 JSON 源数据中的数据元素映射到 通过匹配源中的对象键或名称来获取目标表 名称/值对到目标表中列的名称。这 匹配区分大小写。 Amazon Redshift 表中的列名是 总是小写,所以当你使用‘auto’选项时,匹配 JSON 字段名称也必须是小写的。如果 JSON 字段名称键不是 全部小写,您可以使用 JSONPaths 文件显式映射列 名称到 JSON 字段名称键。

      解决方案是使用jsonpath

      示例 json:

      {
      "Name": "Major",
      "Age": 19,
      "Add": {
      "street":{
      "st":"5 maint st",
      "ci":"Dub"
      },
      "city":"Dublin"
      },
      
      "Category_Name": ["MLB","GBM"]
      
      }
      

      示例表:

      (
      name varchar,
      age int,
      address varchar,
      catname varchar
      );
      

      示例 jsonpath:

      {
      "jsonpaths": [
      "$['Name']",
      "$['Age']",
      "$['Add']",
      "$['Category_Name']"
      ]
      }
      

      示例复制代码:

      copy customer --redshift code
      from 's3://mybucket/customer.json'
      iam_role 'arn:aws:iam::0123456789012:role/MyRedshiftRole'
      json from 's3://mybucket/jpath.json' ; -- Jsonpath file to map fields
      

      示例取自here

      【讨论】:

        【解决方案4】:

        这可能是因为 redshift 表的列名是小写的,而 JSON 文件中的列名是大写的(或驼峰式)。作为一种解决方法,我们可以使用“auto ignorecase”而不是“auto”选项,redshift 会尝试匹配相应的列。 https://docs.aws.amazon.com/en_us/redshift/latest/dg/copy-parameters-data-format.html#copy-json

        复制参数部分中提到了信息。

        【讨论】:

          【解决方案5】:

          现在有一个选项可以在将 json 数据从 s3 加载到 Redshift 时忽略大小写

          COPY crypt.public.coindetails FROM 's3://cryptstreaxxxx/filetest2.json'
          IAM_ROLE 'arn:aws:iam::xxxxxxx:role/service-role/AmazonRedshift-CommandsAccessRole-20211201T210748' 
          FORMAT AS JSON 'auto ignorecase' REGION AS 'us-east-1'
          

          在 Redshift UI 中点击 File Options 并选择如下图所示的选项

          【讨论】:

            猜你喜欢
            • 2014-07-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-03-24
            相关资源
            最近更新 更多