Я столкнулся со странным поведением импорта данных в Redshift из Postgres с помощью AWS Glue.У меня есть поле в таблице postgres lastname varchar(255)
.AWS Glue перемещает этот стол с помощью такого кода:
import sys, boto3
from pyspark.context import SparkContext
from awsglue.job import Job
from awsglue.utils import getResolvedOptions
from awsglue.context import GlueContext
def getDBUrl(database):
dbConnection = glue.get_connection(Name=database)
jdbc_url = dbConnection['Connection']['ConnectionProperties']['JDBC_CONNECTION_URL']
username = dbConnection['Connection']['ConnectionProperties']['USERNAME']
password = dbConnection['Connection']['ConnectionProperties']['PASSWORD']
jdbc_url = jdbc_url + '?user=' + username + '&password=' + password
print jdbc_url
return jdbc_url
args = getResolvedOptions(sys.argv, ['TempDir', 'JOB_NAME'])
sc = sc if 'sc' in vars() else SparkContext()
glueContext = GlueContext(sc)
spark = glueContext.spark_session
job = Job(glueContext)
job.init(args['JOB_NAME'], args)
source_database_connection = 'Postgres'
target_database_connection = 'Redshift'
bound_query = """
(
select COALESCE(max(id),0)
from {0}
) as temp
"""
glue = boto3.client(service_name='glue', region_name='us-east-1')
# Create connection urls
jdbc_url_source = getDBUrl(database=source_database_connection)
jdbc_url_target = getDBUrl(database=target_database_connection)
def extract_and_save(source_table, target_table, source_bound_query):
print "loading {0}".format(target_table)
(upper_bound,) = (spark.read
.jdbc(url=jdbc_url_source, table=source_bound_query)
.first())
df = spark.read.jdbc(url=jdbc_url_source,
table=source_table,
column='id',
lowerBound=1,
upperBound=upper_bound + 10,
numPartitions=50)
df.write.format("com.databricks.spark.redshift") \
.option("url", jdbc_url_target) \
.option("dbtable", target_table) \
.option("tempdir", args["TempDir"]) \
.option("aws_iam_role", "AWS_ROLE") \
.mode("overwrite") \
.option("jdbcdriver", "com.amazon.redshift.jdbc41.Driver") \
.save()
source_user = """
(
SELECT
cast(firstname as VARCHAR(65535)),
last_updated,
registration_date,
date_created,
cast(sex as VARCHAR(65535)),
id,
cast(email as VARCHAR(65535)),
cast(lastname as VARCHAR(65535)),
cast(username as VARCHAR(65535))
FROM user
) as temp
"""
# do extract
extract_and_save(
source_user,
"user",
bound_query.format("user"))
job.commit()
И он отлично работает.Однако, как только я начинаю использовать в полях varchar не VARCHAR(65535)
, а оригинальный размер varchar(255)
, я получаю ошибку при импорте: Missing data for not-null field
.Из STL_LOAD_ERROR я могу узнать, что я получаю пустую строку в поле lastname
.Но в STL_LOAD_ERROR это значение помечено как @NULL@
.В определении таблицы Redshift нет ограничения not null
.
Так почему varchar(255)
вызывает проблемы с обработкой пустых строк, а varchar(65535)
делает это безупречно?