代码之家  ›  专栏  ›  技术社区  ›  Alex

无法使用cqlsh将UTF-8数据复制到锡拉布

  •  0
  • Alex  · 技术社区  · 7 年前

    这就是我正在尝试的:

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

    我得到一个没有堆栈跟踪的模糊错误:

    我的数据和列名(包括已经在ScyllaDB中创建的表中的列名)包含带有德语文本的值。它不是ASCII码,但我还没有找到任何地方可以设置编码,我到处都能看到它似乎在使用 utf-8 已经。我试过了 this 同时,在1135线附近看到,并在我的本地cqlsh(使用 vim $(which cqlsh) ),但没有效果。

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

    我也试过了 cqlsh docker image that I used to install ScyllaDB ,它有完全相同的错误。

    <更新>
    按照建议,我将数据传输到一个文件:

    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标题)。管道输送到

    >>> 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

    这是 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
    

    有人提出了这个答案 UnicodeDecodeError: 'ascii' codec can't decode byte 0xd1 in position 2: ordinal not in range(128) cqlsh.py 开始时,它通过了解码问题,但同一列被报告为无效,并出现另一个错误:

    :1:列名称Ist Einpster无效

    旁注:

    现在我对这个测试失去了兴趣,我只是想尽量不要有一个没有答案的问题,所以请原谅等待的时间。当我把它作为一个分析引擎,再加上Spark作为Tableau的数据源进行试验时,我发现了“更好的”替代品,比如Vertica和ClickHouse。”“更好”,因为两者都有局限性。

    </更新>

    3 回复  |  直到 7 年前
        1
  •  2
  •   Alex    7 年前

    那是什么?

    作为参数传入的查询包含列列表,其中包含具有非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 作为“交互式”,来自提示,而不是管道输入。结果是它不导入任何内容。可以创建一个文件,然后从文件中加载,但这是一个额外的步骤,可能需要几分钟或几小时,具体取决于数据大小。

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

    这可能会奏效,但出于某种原因,我得到了最后一击:

    cqlsh.sql:2:未能导入15行:InvalidRequest-服务器错误:code=2200[无效查询]message=“批处理过大”,将稍后重试,尝试5次中的第4次

    我觉得有趣的是,15行对于分布式存储引擎来说太多了。很可能是unicode相关引擎的一些限制,只是错误的错误消息。或者我错了。尽管如此,最初的问题还是得到了回答,得到了懒汉们的大力帮助。

        2
  •  0
  •   Peter Corless    7 年前

    我看不出你对此有任何答案。UTF-8 这是默认的。

    --encoding ?

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

    如果你在这里没有得到答案,你愿意在我们的网站上提问吗 slack channel ?

        3
  •  0
  •   dyasny    7 年前

    首先,我会尽力消除所有额外的复杂性。尝试将几行转储到CSV中,然后使用 COPY

        4
  •  0
  •   Peter Corless    5 年前

    使用错误位置函数添加新的验证位置 或者第一个字节的字节位置无效 性格该职位被添加到exception中

    用错误验证\u\u位置分两步完成 通过,以保持相同的性能

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