57952


AWS Athena で S3 上にある CSV データを読もうとしたら

[code]

    HIVE_BAD_DATA: Error parsing field value '2019-09-09T00:45:29Z' for field 0: For input string: "2019-09-09T00:45:29Z"
    
[/code]

というエラーが出たのですがこれはどういう意味のエラーなのでしょうか

テーブル定義は

[code]

    CREATE EXTERNAL TABLE `api_log`(
      `time` string COMMENT 'from deserializer', 
      `level` string COMMENT 'from deserializer', 
      `text` string COMMENT 'from deserializer')
    PARTITIONED BY ( 
      `dt` string, 
      `server_name` string)
    ROW FORMAT SERDE 
      'org.apache.hadoop.hive.serde2.OpenCSVSerde' 
    WITH SERDEPROPERTIES ( 
      'escapeChar'='\"\"', 
      'quoteChar'='\"', 
      'separatorChar'=',') 
    STORED AS INPUTFORMAT 
      'org.apache.hadoop.mapred.TextInputFormat' 
    OUTPUTFORMAT 
      'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
    LOCATION
      's3://serverlog.staging/api'
    TBLPROPERTIES (
      'has_encrypted_data'='false', 
      'transient_lastDdlTime'='1567997026')
    
[/code]

読もうとしたCSVは

[code]

    "2019-09-09T00:45:29Z","INFO","""Fuel\\Core\\Request::__construct - Creating a new main Request with URI = \""ping\"""""
    
[/code]

です

Fuel PHP のデフォルトのログ内容を fluentd 経由で S3 に転送して Athena で読めるようにしたいのですが  
改行やカンマやダブルクオートを含むケースがあるので  
何日もはまっていてなかなかうまくいかずに困っています

どうすれば実現できるでしょうか


CC BY-SA 4.0
2019-09-09T03:02:48.487
57940
2019-09-10T08:14:19.347
2019-09-09T03:29:42.017
question
aws csv amazon-s3
AWS Athena で HIVE_BAD_DATA


※この回答は、AWS Athena も Fuel PHP も触ったことのない人がマニュアルを読んだだけで勘で書いたものです。

このエラーはおそらく、ダブルクォーテーションの扱いが上手くいっていないことに起因するものです。具体的には `"` で挟まれている文字列では `""` が
`"` の意味になることが伝わっていません。

というのも、CSV の読み取り方は以下の部分で指定されていますが、`escapeChar` が怪しいです。

[code]

    ROW FORMAT SERDE 
      'org.apache.hadoop.hive.serde2.OpenCSVSerde' 
    WITH SERDEPROPERTIES ( 
      'escapeChar'='\"\"', 
      'quoteChar'='\"', 
      'separatorChar'=',') 
    
[/code]

`escapeChar` にはたとえば `"\\"` (バックスラッシュ **1** 文字) を指定して `\t`
などがエスケープ文字列であることを設定できます。ここに `"\"\""` (ダブルクォート 2 文字) を指定すると `""t`
などがエスケープ文字列であると考えるのが自然で、特に `"""` は `"`
のエスケープということになりますが、これは意図しているものと違いそうです。たとえば質問文にある

[code]

    """Fuel\\Core\\Request::__construct - Creating a new main Request with URI = \""ping\"""""
    
[/code]

をこの規則で左から変換していくと

[code]

    "Fuel\\Core\\Request::__construct - Creating a new main Request with URI = \ping\" (残っている文字列: "")
    
[/code]

までは変換できますが、最後にダブルクォートがふたつ余ってしまい、エスケープの相手がいません。おそらくこのあたりでエラーになっているのではないでしょうか。

### 参考

  * [CSV を処理するための OpenCSVSerDe](https://docs.aws.amazon.com/ja_jp/athena/latest/ug/csv.html) \-- AWS ドキュメント 
    * パッと見た感じ、このドキュメントに載っている「例: \t または \n をエスケープ」という例そのままにすれば解決できそうに見えます。つまり `escapeChar` を `"\\"` にすると良さそうです。
    * ただし `""` には言及が無いので、対応しているか確かめる必要はあります。


CC BY-SA 4.0
2019-09-09T16:35:28.030
57952
2019-09-10T08:14:19.347
2019-09-10T08:14:19.347
19110
19110
57940
answer