【问题标题】:Redshift: Truncate VARCHAR value automatically on INSERT or maybe use max length?Redshift:在 INSERT 上自动截断 VARCHAR 值还是使用最大长度?
【发布时间】:2016-01-13 06:10:39
【问题描述】:

在执行 INSERT 时,Redshift 不允许您在表中插入比目标字段更长/更宽的字符串值。观察:

CREATE TEMPORARY TABLE test (col VARCHAR(5));
-- result: 'Table test created'

INSERT INTO test VALUES('abcdefghijkl');
-- result: '[Amazon](500310) Invalid operation: value too long for type character varying(5);'

一种解决方法是强制转换值:

INSERT INTO test VALUES('abcdefghijkl'::VARCHAR(5));
-- result: 'INSERT INTO test successful, 1 row affected'

令人讨厌的部分是,现在我的所有代码都必须在每个 VARCHAR 字段的每个 INSERT 上都有这些强制转换语句,否则应用程序代码必须在尝试构造查询之前截断字符串;无论哪种方式,这意味着列的宽度规范必须进入应用程序代码,这很烦人。

有没有更好的方法用 Redshift 做到这一点?如果有一些选项可以让服务器截断字符串并像使用 MySQL 一样执行(并可能引发警告),那就太好了。

我可以做的一件事就是将这些特定字段声明为一个非常大的 VARCHAR,甚至可能是 65535(最大值)。

create table analytics.testShort (a varchar(3));
create table analytics.testLong (a varchar(4096));
create table analytics.testSuperLong (a varchar(65535));

insert into analytics.testShort values('abc'); 
insert into analytics.testLong values('abc');
insert into analytics.testSuperLong values('abc');

-- Redshift reports the size for each table is the same, 4 mb

我发现这种方法的一个缺点是,如果在 group by/join/etc 中使用该列会导致性能不佳:

https://discourse.looker.com/t/troubleshooting-redshift-performance-extensive-guide/326 (搜索 VARCHAR)

我想知道,如果您打算永远不要在 group by、join 等中使用此字段,是否没有任何危害。

在我的场景中需要注意的一些事情:是的,我真的不关心截断可能会丢失的额外字符,不,我没有办法强制源文本的长度。我正在从外部来源捕获消息和 URL,这些消息和 URL 通常属于字符长度的特定范围,但有时会有更长的字符。它们是否被截断在我们的应用程序中并不重要。

【问题讨论】:

    标签: text amazon-redshift


    【解决方案1】:

    自动截断字符串以匹配列宽的唯一方法是使用带有选项TRUNCATECOLUMNS的COPY命令

    将列中的数据截断为适当数量的字符,以便 它符合列规范。仅适用于具有 VARCHAR 或 CHAR 数据类型,以及大小不超过 4 MB 的行。

    否则,您将不得不使用以下两种方法之一来处理字符串的长度:

    1. 将您的值显式转换为所需的 VARCHAR:

      INSERT INTO test VALUES(CAST('abcdefghijkl' AS VARCHAR(5)));

    2. 使用LEFT and RIGHT 字符串函数截断字符串:

      INSERT INTO test VALUES(LEFT('abcdefghijkl', 5));

    注意: CAST 应该是您的首选,因为它可以正确处理多字节字符。 LEFT 将根据 characters 而不是 bytes 的数量截断,如果您的字符串中有一个多字节字符,您最终可能会超出列的限制.

    【讨论】:

    • 谢谢,是的,这是我们很久以前就确定的。对于大批量插入,我们使用 COPY 的 truncate 选项,这很明显。对于其他地方完成的其他 INSERT 和 UPDATE 操作,我们使用 :: 运算符进行 CAST。
    • +1 转换,它将处理字节。 LEFT/RIGHT 处理字符,因此如果您的源字符串是多字节字符串,则 LEFT/RIGHT 可能会返回比预期更长的 VARCHAR 字节。 IE。 LEFT(foobar, 5) 可能会返回一个比 VARCHAR(5) 更长的字符串。
    猜你喜欢
    • 1970-01-01
    • 2019-03-06
    • 2015-07-18
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 2016-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多