从S3外部Delta表创建目录:会话重启后Schema与表无法识别
我在S3中存储了一批Delta表,创建代码如下:
DF.write.format("delta").option("path","s3a://deltalake_silver/general_schema/table_a").saveAsTable("general_schema.table_a")
表创建在general_schema Schema中,创建后立即执行以下代码:
spark._jsparkSession.catalog().tableExists("general_schema", "table_a")
返回结果为True。
但创建新Spark会话或重启Notebook集群后,返回结果为False。执行以下代码时:
spark.sql("show tables from general_schema").show()
抛出异常:
AnalysisException: [SCHEMA_NOT_FOUND] The schema
general_schemacannot be found. Verify the spelling and correctness of the schema and catalog. If you did not qualify the name with a catalog, verify the current_schema() output, or qualify the name with the correct catalog.
以下是我创建Spark会话的代码,请问需要添加什么配置才能让目录从S3桶加载?
builder = SparkSession.builder.appName("MyDeltaLakeApp") \ .config("spark.hadoop.fs.s3a.access.key", aws_access_key_id) \ .config("spark.hadoop.fs.s3a.secret.key", aws_secret_access_key) \ .config("spark.hadoop.fs.s3a.aws.credentials.provider", "org.apache.hadoop.fs.s3a.SimpleAWSCredentialsProvider") \ .config("spark.hadoop.fs.s3a.endpoint", "s3.sa-east-1.amazonaws.com") \ .config("spark.jars.packages", "org.apache.hadoop:hadoop-aws:3.3.4") \ .config('spark.hadoop.fs.s3a.path.style.access', True) \ .config("spark.hadoop.fs.s3a.impl", "org.apache.spark.sql.delta.storage.S3SingleDriverLogStore") \ .config("spark.sql.extensions", "io.delta.sql.DeltaSparkSessionExtension") \ .config("spark.sql.catalog.spark_catalog", "org.apache.spark.sql.delta.catalog.DeltaCatalog") spark = configure_spark_with_delta_pip(builder).getOrCreate()
你需要配置基于S3的Delta Lake元数据目录,让Spark跨会话读取存储在S3的Schema和表元数据,具体修改如下:
1. 修正现有配置错误
你当前配置中spark.hadoop.fs.s3a.impl被错误设置为日志存储类,需要改回S3文件系统实现:
.config("spark.hadoop.fs.s3a.impl", "org.apache.hadoop.fs.s3a.S3AFileSystem")
2. 添加外部Delta Catalog配置
新增指向S3根目录的外部Catalog,让Spark直接从S3读取元数据:
.config("spark.sql.catalog.delta_catalog", "org.apache.spark.sql.delta.catalog.DeltaCatalog") \ .config("spark.sql.catalog.delta_catalog.path", "s3a://deltalake_silver/")
这里delta_catalog是自定义Catalog名称,path填写你存储所有Delta表的S3根目录(即包含general_schema的父目录)。
3. (可选)设置默认Catalog
如果希望默认使用该S3 Catalog,避免每次操作都指定Catalog名称,可添加:
.config("spark.sql.defaultCatalog", "delta_catalog")
修改后的完整配置
builder = SparkSession.builder.appName("MyDeltaLakeApp") \ .config("spark.hadoop.fs.s3a.access.key", aws_access_key_id) \ .config("spark.hadoop.fs.s3a.secret.key", aws_secret_access_key) \ .config("spark.hadoop.fs.s3a.aws.credentials.provider", "org.apache.hadoop.fs.s3a.SimpleAWSCredentialsProvider") \ .config("spark.hadoop.fs.s3a.endpoint", "s3.sa-east-1.amazonaws.com") \ .config("spark.jars.packages", "org.apache.hadoop:hadoop-aws:3.3.4,io.delta:delta-core_2.12:2.4.0") \ .config('spark.hadoop.fs.s3a.path.style.access', True) \ .config("spark.hadoop.fs.s3a.impl", "org.apache.hadoop.fs.s3a.S3AFileSystem") \ .config("spark.delta.logStore.class", "org.apache.spark.sql.delta.storage.S3SingleDriverLogStore") \ .config("spark.sql.extensions", "io.delta.sql.DeltaSparkSessionExtension") \ .config("spark.sql.catalog.spark_catalog", "org.apache.spark.sql.delta.catalog.DeltaCatalog") \ # 新增外部Catalog配置 .config("spark.sql.catalog.delta_catalog", "org.apache.spark.sql.delta.catalog.DeltaCatalog") \ .config("spark.sql.catalog.delta_catalog.path", "s3a://deltalake_silver/") \ # 可选:设置默认Catalog .config("spark.sql.defaultCatalog", "delta_catalog") spark = configure_spark_with_delta_pip(builder).getOrCreate()
你之前用saveAsTable时,默认将表元数据存储在Spark内置Catalog(仅当前会话有效),而非S3。配置外部Delta Catalog后,Spark会直接从S3读取Delta表的元数据文件,Schema和表信息会持久化在S3中,跨会话、跨集群都能识别。
内容的提问来源于stack exchange,提问作者Andrés Bustamante

