Как я могу надежно использовать значения даты и времени в файлах паркета для заполнения (снежинки) таблиц - PullRequest
1 голос
/ 12 февраля 2020

TLDR

Как мне убедиться, что значения даты и времени в моем файле паркета правильно скопированы в таблицу снежинок?

Описание

Я использую файл паркета для вставьте данные на сцену в снежинка . Этот файл затем используется для COPY INTO таблицы снежинок.

Все работает хорошо, кроме значений даты и времени: в зависимости от того, использую ли я fastparquet или pyarrow для локального сохранения файла паркета, значения даты и времени являются правильными или нет (тип данных TIMESTAMP_NTZ(9) в снежинке) :

# With fastparquet:
ID    SOME_TIMESTAMP
----------- 
1     2020-02-02 00:35:28.000
2     2020-02-02 00:35:31.857
3     2020-02-02 00:35:21.000

# With pyarrow:
ID    SOME_TIMESTAMP
----------- 
1     52057-05-03 07:06:40.000
2     52057-05-03 08:10:57.000
3     52057-05-03 05:10:00.000

Однако в pandas кадры данных идентичны, и оба имеют одинаковые типы: datetime64[ns]

1 2020-02-02 00:35:28.000
2 2020-02-02 00:35:31.857
3 2020-02-02 00:35:21.000

Поэтому я считаю, что проблема кроется в Как fastparquet и pyarrow работают со значениями даты и времени, а затем с тем, как снежинка читает файлы паркета.

Идеи решения

На данный момент я могу придумать три способа решения этой проблемы:

  1. Убедитесь, что файлы паркета сохранены с fastparquet. Несмотря на то, что я не могу контролировать это сразу, я всегда могу открыть каждый файл паркета с помощью pd.read_parquet() и сохранить его с помощью pd.to_parquet(fname, engine='fastparquet'). Даже при том, что это работает, я действительно хотел бы избежать этой опции, так как файлы могут стать очень большими.
  2. Попытайтесь выяснить, как файлы были сохранены, используя метаинформацию. Если используемый двигатель не fastparquet, откройте и сохраните файл с fastparquet. Это значительно уменьшит проблему, о которой я говорил выше, потому что я открываю и сохраняю только те файлы, которые, как я знаю, могут вызвать проблемы.
  3. Убедитесь, что Snowflake правильно обрабатывает значения меток времени.

Для go с вариантом 2 мне нужно как-то различать guish (в Python), как был сохранен паркет.

Другие переулки, которые я спустил

Снежинка позволяет мне указать используемое сжатие, например COMPRESSION = AUTO (по умолчанию) или COMPRESSION = SNAPPY, как описано здесь . Однако AFAIK и pyarrow, и fastparquet используют это сжатие. Кроме того, опция AUTO должна фиксировать это, согласно документации.

1 Ответ

1 голос
/ 12 февраля 2020

Хотя я не уверен на 100%, что делают pandas или python. Я видел это раньше, и для нас это было из-за того, что эпоха пыталась преобразовать в метки времени. Когда эти данные передаются, создается впечатление, что они преобразуются в эпоху, а затем CAST ( :: TIMESTAMP_NTZ ) в TIMESTAMP_NTZ, который по какой-то причине дает шкалу 0 вместо 9.

Я рекомендую использовать функцию для CONVERT ( [TRY_] TO_TIMSTAMP (<значение>, [масштаб / формат] )) значения в метке времени. Это даст вам возможность указать функция, в какой тип данных передается и как она должна интерпретировать эти данные. С CAST вы оставляете решать Snowflake.

Вот пример кода, который, надеюсь, поможет визуализировать ситуацию. использовал ваши примеры отметок времени, которые изначально были построены в виде строки. Затем я преобразовал (и преобразовал для полноты) в отметку времени, затем в миллисекунды, затем использовал миллисекунды, чтобы вернуться к отметке времени.

SELECT $1 AS C1
    ,$2 AS C2
    // strings cast or converted to timestamps both result in the same output, so we can use either to calculate the MS from EPOCH start
    ,$2::TIMESTAMP_NTZ AS STRING_CAST_TO_DTTM
    ,TO_TIMESTAMP_NTZ($2) AS STRING_CONVERT_TO_DTTM
    ,DATEDIFF('MS','0',STRING_CAST_TO_DTTM) AS MS
//    ,DATEDIFF('MS','0',STRING_CONVERT_TO_DTTM) AS MS
    // the lines below are integers being CONVERTED to timestamp and the scale is an explicit parameter of the function; note that everything converts correctly BASED ON SCALE
    ,TO_TIMESTAMP_NTZ(MS,0) AS CONVERT_NTZ0
    ,TO_TIMESTAMP_NTZ(MS,3) AS CONVERT_NTZ3
    ,TO_TIMESTAMP_NTZ(MS,6) AS CONVERT_NTZ6
    ,TO_TIMESTAMP_NTZ(MS,9) AS CONVERT_NTZ9
    // the lines below are integers being CAST to timestamp; note that the scale does not matter everything is returned as TIMESTAMP_NTZ(0)
    ,MS::TIMESTAMP_NTZ(0) AS CAST_NTZ0
    ,MS::TIMESTAMP_NTZ(3) AS CAST_NTZ3
    ,MS::TIMESTAMP_NTZ(6) AS CAST_NTZ6
    ,MS::TIMESTAMP_NTZ(9) AS CAST_NTZ9
FROM VALUES 
(1,'2020-02-02 00:35:28.000')
,(2,'2020-02-02 00:35:31.857')
,(3,'2020-02-02 00:35:21.000')
;

// use this to see the resulting data types for each column
DESC RESULT LAST_QUERY_ID();

Комментарий, если У вас есть вопросы по поводу приведенного выше кода.

...