Amazon Redshift: как связать строку `stl_load_errors` с правильным именем таблицы, если идентификатор найденной таблицы не совпадает? - PullRequest
1 голос
/ 02 апреля 2019

Краткое описание проблемы

Я использую запрос COPY для загрузки данных из S3 в таблицу Redshift t1.

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

Но в случае ошибок, в зависимости от загруженной таблицы, я не всегда могу правильно отследить, какая ошибка произошла во время загрузки этой конкретной таблицы, потому что дляВ некоторых загруженных таблицах, таких как t1, идентификатор таблицы tbl, найденный в stl_load_errors, не соответствует ожидаемому для таблицы t1.

Я фильтрую stl_load_errors как на filename, так и на *1015*.tbl, поскольку один и тот же файл S3 может быть загружен в разные таблицы, поэтому фильтрация только по имени файла не является безопасным способом проверки наличия ошибок во время одного конкретного запроса COPY.

Подробности

Загруженное имя таблицы не отображается в этой таблице, вместо этого мы получаем целочисленный идентификатор 1234567 в столбце tbl.Мы должны объединиться с другой таблицей stv_tbl_perm, которая содержит имя и идентификатор, чтобы получить имя.Эта «хитрость» показана в документации Redshift.

Для некоторых таблиц, таких как t1, строка ошибки, которую я могу найти в stl_load_errors после использования COPY t1 ..., будет иметь идентификатор 1234567 в tbl столбец, который не соответствует ни одному из найденных в stv_tbl_perm.Как будто это был идентификатор временной таблицы.

Затем, когда я смотрю в stv_tbl_perm для "name"='t1', я нахожу идентификатор 10111213 в столбце id, но это не тотЯ видел в stl_load_errors.

Что делает его еще более запутанным, так это то, что мой метод фильтрации ошибок по файлам и таблицам прекрасно работает для некоторых таблиц Redshift, найденный id является ожидаемым,совпадает с правильным значением name в stv_tbl_perm.

Почему моя копия COPY для таблицы проходит через то, что похоже на временную таблицу для одной таблицы, а не для других?

Воспроизведение

Я попытался максимально упростить свой процесс обмена, и мне удалось воспроизвести мою проблему следующим образом.

1.Создайте таблицу, вставьте строки, чтобы она не была пустой, и проверьте ее.

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;

2.Создайте файл S3 с преднамеренной ошибкой типа

Я пишу символ в столбце «id», чтобы он вызывал ошибку типа во время загрузки.

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 ','; 

Убедитесь, чтозамените my-bucket, 1111111111 и my-user собственными значениями.

3.Загрузите этот файл в таблицу, используя COPY

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.

4.Проверьте идентификатор таблицы в новой строке ошибки в stl_load_errors

SELECT * 
FROM stl_load_errors 
where trim(filename) = 's3://my-bucket/redshift-load-error-table-id/unload/t1_000';

Мы находим строку, соответствующую файлу, и сохраняем идентификатор таблицы, найденный в столбце tbl, скажем "tbl" = 1234567 (вы получите что-то другое).

5.Посмотрите этот идентификатор таблицы в stv_tbl_perm, чтобы получить имя таблицы

select *
from stv_tbl_perm 
where id='1234567';

Это ничего не возвращает, найденный идентификатор не соответствует какой-либо постоянной таблице, указанной в stv_tbl_perm.Как будто это был идентификатор временной таблицы.

6.Найдите ожидаемый идентификатор таблицы, которую мы загрузили в

select *
from stv_tbl_perm 
where name='t1';

Это возвращает 10111213 (вы получите что-то другое), и это идентификатор, который я должен был получить в tbl столбец таблицы stl_load_errors.

Если я попытаюсь выполнить еще одно КОПИРОВАНИЕ с ошибкой, в таблице ошибок появится другая строка с другим идентификатором, отличным от обоих предыдущих идентификаторов.Это также указывает на то, что это может быть идентификатор временной таблицы.

Следствие

Поэтому я не могу фильтровать stl_load_errors для конкретной таблицы, к которой я применил запрос COPY.

Удивительно, но этот процесс отлично работает для некоторых моих таблиц иЯ не могу найти никакой разницы в том, как я делаю это между таблицами, для которых он работает, и таблицами, для которых он не работает.

Я еще не нашел ссылки на эту проблему в Интернете,Требуется много деталей, поэтому поиск тоже затруднен.

Есть идеи?

Ответы [ 2 ]

1 голос
/ 19 апреля 2019

Это было определено как фактическая проблема Redshift из-за недавней функции Redshift, разработанной инженером AWS на форуме разработчиков AWS, где я опубликовал свою проблему.

@ joeharris76-AWS:

Хорошо, спасибо, что сообщили об этом.Мы определили источник этой проблемы и исследуем исправление.Когда это будет исправлено, в наших регулярных сообщениях о техобслуживании в верхней части форума будет появляться примечание.

Это связано с функцией автоматического DISTSTYLE, которую мы недавно добавили.Для таблиц DISTSTYLE AUTO, которые в настоящее время являются ALL, мы загружаем новые данные во временную таблицу и затем проверяем, требуется ли для новых добавленных строк преобразование таблицы из ALL в EVEN.https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_TABLE_NEW.html

DISTSTYLE {AUTO |ДАЖЕ |КЛЮЧ |ВСЕ} По умолчанию установлено значение АВТО.… АВТО: Amazon Redshift назначает оптимальный стиль распространения на основе данных таблицы.Например, если указан стиль распространения AUTO, Amazon Redshift первоначально назначает ВСЕ распределение небольшой таблице, а затем изменяет таблицу на ДАЖЕ распределение, когда таблица увеличивается.Изменение распределения происходит в фоновом режиме, через несколько секунд.…

Существует два способа обойти это:

  1. Определить явный DISTSTYLE EVEN, KEY или ALL в загружаемой таблице.Я рекомендую эту опцию в первую очередь для таблиц, которые могут использовать KEY diststyle.Если вы не используете KEY, то AUTO diststyle будет наиболее эффективным.

  2. Извлеките идентификатор запроса из stl_load_errors, извлеките SQL из stl_querytext для запроса, а затем найдитетаблица по имени из 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 table, и это тоже работает в моем случае с воспроизведением, но я не нахожу это очень чистым и неэффективным для анализа строки, чтобы найти имя таблицы внутри, поэтому я буду придерживаться добавления DISTSTYLE EVEN в моем текущемслучаи.

0 голосов
/ 02 апреля 2019

Вместо stv_tbl_perm используйте pg_class. Вы можете использовать столбцы oid (идентификатор объекта базы данных) в таблицах каталога Postgres как объединяющие столбцы

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

Пожалуйста, дайте мне знать, если это решит вашу проблему.

...