Не удается скопировать данные UTF-8 в ScyllaDB с помощью cqlsh

Я пытаюсь скопировать большой набор данных из Postgresql в ScyllaDB, который должен быть совместим с Cassandra.

Вот что я пытаюсь:

psql <db_name> -c "COPY (SELECT row_number() OVER () as id, * FROM ds.my_data_set LIMIT 20) TO stdout WITH (FORMAT csv, HEADER, DELIMITER ';');" \
 | \
CQLSH_HOST=172.17.0.3 cqlsh -e 'COPY test.mytable (id, "Ist Einpöster", [....]) FROM STDIN WITH DELIMITER = $$;$$ AND HEADER = TRUE;'

Я получаю непонятную ошибку без трассировки стека:

: 1: кодек ascii не может декодировать байт 0xc3 в позиции 9: порядковый номер не в диапазоне (128)

Мои данные и имена столбцов, включая те, которые уже есть в созданной таблице в ScyllaDB, содержат значения с немецким текстом. Это не ASCII, но я не нашел нигде для установки кодировки, и везде, где я смотрел, казалось, что уже используется utf-8. Я также попробовал это и увидел около строки 1135, что и изменил его в моем локальном cqlsh (используя vim $(which cqlsh)), но это не повлияло.

Я использую cqlsh 5.0.1, установленный с помощью pip. (как ни странно было pip install cqlsh==5.0.4)

Я также попробовал cqlsh из образа докера, который я использовал для установки ScyllaDB, и он имеет точный та же ошибка.

‹Update›
Как и было предложено, я отправил данные в файл:

psql <db_name> -c "COPY (SELECT row_number() OVER (), * FROM ds.my_data_set ds) TO stdout WITH (FORMAT csv, HEADER);" | head -n 1 > test.csv

Я проредил его до первой строки (заголовок CSV). Подключение к cqlsh заставило его плакать с той же ошибкой. Затем, используя интерактивную оболочку python3.5, я сделал следующее:

>>> with open('test.csv', 'rb') as fp:
...   data = fp.read()
>>> data
b'row_number,..... Ist Einp\xc3\xb6ster ........`

Вот и мы, \xc3 во плоти. Это UTF-8?

>>> data.decode('utf-8')
'row_number,....... Ist Einpöster ........`

Да, это utf-8. Так как же происходит ошибка?

>>> data.decode('ascii')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 336: ordinal not in range(128)

Тот же текст ошибки, так что, вероятно, это тоже Python, но без трассировки стека я понятия не имею, где это происходит, а кодировки по умолчанию - utf-8. Я попытался заменить значение по умолчанию на utf-8, но ничего не изменилось. Тем не менее, где-то что-то пытается декодировать поток с помощью ASCII.

Это locale на сервере / клиенте:

LANG=
LANGUAGE=
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=en_US.UTF-8

Кто-то в Slack предложил этот ответ UnicodeDecodeError: кодек ascii не может декодировать байт 0xd1 в позиции 2: порядковый номер не в диапазоне (128) После того, как я добавил последние 2 строки в cqlsh.py в начале, проблема с декодированием прошла, но то же самое столбец был зарегистрирован как недопустимый с другой ошибкой:

: 1: Недействительное имя столбца Ist Einpöster

примечание:

На данный момент я потерял интерес к этому тесту, и я просто пытаюсь не оставить без ответа вопрос, поэтому, пожалуйста, извините за время ожидания. Когда я пробовал его как аналитический движок вместе со Spark, как источник данных для Tableau, я нашел «лучшие» альтернативы, такие как Vertica и ClickHouse. «Лучше», потому что у них обоих есть ограничения.

‹/Update›

Как я могу завершить этот импорт?


person AlexanderMP    schedule 22.11.2018    source источник
comment
1. Можете ли вы поделиться схемой из Postgresql (включая типы данных) по сравнению со схемой, созданной вами на Scylla / Cassandra (включая типы данных). Иногда требуются переделки. 2. Есть ли в ваших данных какие-либо значения NULL?   -  person TomerSan    schedule 28.11.2018
comment
@TomerSan, очевидно, это не имеет значения. Мне удалось воспроизвести ошибку с помощью таких простых вещей, как этот echo "not important what you write here" | cqlsh --encoding='utf-8' -e 'COPY test.whatever (id, "ö") FROM STDIN WITH DELIMITER = $$;$$ AND HEADER = TRUE;' Должно существовать только пространство ключей. Остальное терпит неудачу до любой проверки структуры. Это, очевидно, синтаксический анализатор запроса, поскольку позиция недопустимого символа - это позиция ö в имени столбца.   -  person AlexanderMP    schedule 29.11.2018


Ответы (4)


Что это было?

Запрос, переданный в качестве аргумента, содержал список столбцов, который содержал этот столбец с символом, отличным от ASCII. В какой-то момент cqlsh проанализировал их как ascii, а не utf-8, что привело к этой ошибке.

Как это было исправлено?

Первой попыткой было добавить эти 2 строки в cqlsh:

reload(sys)
sys.setdefaultencoding('utf-8')

но из-за этого скрипт по-прежнему не мог работать с этим столбцом.

Вторая попытка заключалась в том, чтобы просто передать запрос из файла. Если вы не можете, знайте, что bash поддерживает подстановку процесса, поэтому вместо этого:

cqlsh -f path/to/query.cql

вы можете иметь

cqlsh -f <(echo "COPY .... FROM STDIN;")

И все это здорово, кроме того, что тоже не работает. cqlsh понимает stdin как «интерактивный» из приглашения, а не по конвейеру. В результате ничего не импортируется. Можно просто создать файл и загрузить его из файла, но это дополнительный шаг, который может занять минуты или часы, в зависимости от размера данных.
К счастью, в системах POSIX есть эти виртуальные файлы, такие как '/ dev / stdin' , поэтому приведенная выше команда эквивалентна этой:

cqlsh -f <(echo "COPY .... FROM '/dev/stdin';")

за исключением того, что cqlsh теперь думает, что у вас действительно есть файл, и читает его как файл, так что вы можете передавать свои данные и быть счастливыми.

Это, наверное, сработало бы, но по какой-то причине я получил последний удар:

cqlsh.sql: 2: Не удалось импортировать 15 строк: InvalidRequest - Ошибка с сервера: code = 2200 [Недействительный запрос] message = «Пакет слишком большой», повторите попытку позже, попытка 4 из 5

Мне кажется забавным, что 15 строк - это слишком много для механизма распределенного хранения. И вполне вероятно, что это снова какое-то ограничение движка, связанное с юникодом, и просто неправильное сообщение об ошибке. Или я ошибаюсь. Тем не менее, на первоначальный вопрос был дан ответ, с некоторой БОЛЬШОЙ помощью со стороны ребят из Slack.

person AlexanderMP    schedule 29.11.2018
comment
15 строк не удалось, потому что внутри каждой из них у вас был слишком большой пакет, вывод немного сбивает с толку - person dyasny; 29.11.2018

Я не думаю, что вы когда-нибудь получили на это ответ. UTF-8 должен использоваться по умолчанию.

Вы пробовали --encoding?

Документы: https://docs.scylladb.com/getting-started/cqlsh/

Если вы не получили здесь ответа, не могли бы вы задать его на нашем канале Slack?

person Peter Corless    schedule 27.11.2018
comment
Я также немного искал этот код ошибки, 0xc3. Это мне кое-что напомнило. Мне было интересно, не страдают ли вы от каких-то данных, которые на самом деле не UTF-8, а могут быть Unicode. Что-то происходит при кодировании / декодировании. Я читал эту ветку о людях, которые сталкиваются с одной и той же ошибкой, хотя, очевидно, по разным причинам. Но ответы могут помочь вам продумать, где может быть ошибка. stackoverflow.com/questions/24475393/ - person Peter Corless; 27.11.2018
comment
Я попробую канал Slack, просто из любопытства. Я думаю, что это не проблема UTF-8, поскольку он пробует кодек ASCII в соответствии с ошибкой. Python может без проблем декодировать поток с UTF-8. - person AlexanderMP; 29.11.2018

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

person dyasny    schedule 27.11.2018
comment
Спасибо за предложение. Я сомневаюсь, что psql имеет к этому какое-то отношение, поскольку мы используем этот метод и передаем его по конвейеру из сотен источников и никогда не сталкивались с этой проблемой. Но я все же попробовал и обновил вопрос. - person AlexanderMP; 29.11.2018
comment
Хорошо, мне кажется, проблема с питоном. Вы пробовали с новым cqlsh? Я полагаю, вы можете получить тот, который поставляется с кассандрой, или просто установить последнюю версию через pip - person dyasny; 29.11.2018
comment
В конце концов я решил эту ошибку. Подробности в моем ответе. Спасибо за ваше время и усилия. - person AlexanderMP; 29.11.2018

Обновление: utf8: вывести недопустимую позицию символа UTF-8

Добавьте новую функцию validate_with_error_position, которая возвращает -1, если данные являются допустимой строкой UTF-8 или, в противном случае, байтовой позицией первого недопустимого символа. Позиция добавляется в сообщения об исключениях всех ошибок синтаксического анализа UTF-8 в Scylla.

validate_with_error_position выполняется в два прохода, чтобы сохранить ту же производительность в общем случае, когда строка действительна.

person Peter Corless    schedule 14.09.2020