1

我正在尝试将一个大型数据集从 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' 编解码器无法解码位置 9 中的字节 0xc3:序数不在范围内(128)

我的数据和列名,包括已经在 ScyllaDB 中创建的表中的那些,包含带有德语文本的值。它不是 ASCII,但我还没有找到任何设置编码的地方,而且在我看来它似乎utf-8已经在使用的任何地方。我也试过这个,并在 1135 行附近看到,并在我的本地 cqlsh 中更改它(使用vim $(which cqlsh)),但它没有效果。

我正在使用cqlsh 5.0.1,使用 pip 安装。(奇怪的是pip install cqlsh==5.0.4

我还尝试了我用来安装 ScyllaDBcqlsh的docker 映像,它有完全相同的错误。

<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 交互式 shell,我这样做了:

>>> 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' codec can't decode byte 0xd1 in position 2: ordinal not in range(128) 一旦我cqlsh.py在开头添加了最后两行,它就解决了解码问题,但是同一列被报告为无效并出现另一个错误:

:1:无效的列名 Ist Einpöster

边注:

在这一点上,我对这个测试失去了兴趣,我只是想让一个没有答案的问题,所以请原谅等待时间。当我尝试将其作为分析引擎与 Spark 结合作为 Tableau 的数据源时,我发现了“更好”的替代方案,例如 Vertica 和 ClickHouse。“更好”是因为它们都有局限性。

</更新>

如何完成此导入?

4

4 回答 4

2

它以前如何?

作为参数传入的查询包含列列表,其中包含具有非 ASCII 字符的列。在某些时候,将cqlsh它们解析为 ascii 而不是utf-8,这会导致此错误。

它是如何修复的?

第一次尝试是将这两行添加到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 [Invalid query] message="Batch too large",稍后重试,尝试 4 of 5

我认为 15 行对于分布式存储引擎来说太多了,这很有趣。而且很可能这又是与 unicode 相关的引擎的一些限制,并且只是错误的错误消息。或者我错了。尽管如此,最初的问题还是得到了解答,并得到了 Slack 人员的大力帮助。

于 2018-11-29T16:11:47.420 回答
0

我看你从来没有得到过这个问题的答案。UTF-8应该是默认值。

你试过了--encoding吗?

文档:https ://docs.scylladb.com/getting-started/cqlsh/

如果您在这里没有得到答案,您想在我们的slack 频道上提问吗?

于 2018-11-27T18:35:37.910 回答
0

我会先尝试消除您在其中的所有额外复杂性。尝试将几行转储到 CSV,然后使用将其加载到 ScyllaCOPY

于 2018-11-27T19:21:27.870 回答
0

更新:utf8:打印无效的 UTF-8 字符位置

添加新的 validate_with_error_position 函数,如果数据是有效的 UTF-8 字符串或第一个无效字符的字节位置,则返回 -1。该位置被添加到 Scylla 中所有 UTF-8 解析错误的异常消息中。

validate_with_error_position 分两次完成,以便在字符串有效的常见情况下保持相同的性能。

https://github.com/scylladb/scylla/commit/ffd8c8c505b92a71df7e34d5196c7545f11cb12f

于 2020-09-14T20:00:49.393 回答