我正在使用AWS DMS将数据从Oracle迁移到Redshift。我对这个专栏有意见:MID_NM。在Oracle中,此列为:MID_NM VARCHAR2(40)
在Redshift中,我创建了相同的表,并将该列的数据类型转换为:mid_nm VARCHAR(40) ENCODE lzo
但是当我运行迁移任务时,它试图转换Oracle列中的原始文本,即:JAMES POLISH POLISHE GRANDCHILD’S FALSE
(39个字符)
这是:JAMES POLISH POLISHE GRANDCHILD...S FALSE
(41个字符)
这是错误的,因为Oracle和Redshift中的两个字段都只能容纳40个字符。由于撇号/引号正在转换为省略号(...),因此它超出了Redshift中的字符限制。我不知道该怎么解决?它为什么要这样做?是不是“编码伊索”的事?我尝试添加一个DMS转换规则来将列更改为string
,这样也许它会将原始文本转换为文字字符串,而不是尝试转换任何东西......它不起作用。
1条答案
按热度按时间wlwcrazw1#
我相信问题在于,甲骨文中的字符不是撇号,而是正确的单引号。撇号是ASCII x27,但右单引号是x2019,在多字节UTF-8中需要3个字节来表示。参见https://en.wikipedia.org/wiki/UTF-8
在Redshift中,varchar数据类型的长度是以字节为单位,而不是字符。因此,对于这些多字节字符,varchar中需要更多的空间。参见https://docs.aws.amazon.com/redshift/latest/dg/c_Supported_data_types.html
我怀疑'...'来自一个日志记录表,该表使用每个点表示字符串中的一个非异步字节。因此,您可能需要增加varchar长度,以解决数据中的这些多字节字符。如果在任何字符串中只有少数几个非ASCII字符,则大小增加不应该太多(1.25倍)。如果你处理的字符串可能大部分都是非ASPACK字符,那么大小可能需要显着增加(最多增加4倍)。
要确切地知道你需要多少额外的空间,你可以将数据加载到一个指定了long varchar长度的临时表中,然后比较MAX(LENGHT(MID_NM))和MAX(OCTET_LENGTH(MID_NM))- Octet_length()以字节为单位给出字符串的长度,length()以字符为单位给出长度。octet_length给出了varchar列存储信息所需的长度。
你可以在你的表中4X所有的varchar列,而不再遇到这种情况,但是这样做会影响性能。当数据在磁盘上压缩时(在本例中为LZO),运行的查询必须分配足够的内存来存储表中每行的最大可能字符串。因此,varchar大小的4X将浪费内存中用于运行查询的空间。这种影响可以衡量吗?- 这取决于集群运行时的最大内存值和varchar列的大小。
一个折中的方法是将所有的varchar列都放大2倍,其中用户输入的数据可以包含多字节字符,而对于不能包含多字节字符的系统定义的数据,保持在1倍。这仍然浪费空间,但不需要大量的数据分析来知道正确的大小。这个解决方案仍然暴露于一些可能的数据大小问题,但它们应该是非常罕见的-就像有人把所有的符号放在一个字段中。如果您希望用户输入更罕见的字符集(例如泰语),您可能希望将其提高到3X。
另一种解决方案是在加载到Redshift之前将所有数据Map到ascovery。如果你所处理的只是几个字符(比如右单引号或重音字母),那么这个Map可以在几乎没有信息损失的情况下完成,也不需要修改表。