在单个位置激发模式管理



问题

管理Spark表架构的最佳方式是什么?你认为方案2有什么缺点吗?你能提出更好的替代方案吗

我看到的解决方案

选项1:为代码和元存储保留单独的定义

这种方法的缺点是您必须不断地保持它们的同步(容易出错(。另一个缺点是,如果表有500列,就会变得很麻烦。

create_some_table.sql[第一个定义]

-- Databricks syntax (internal metastore)
CREATE TABLE IF NOT EXISTS some_table (
Id int,
Value string,
...
Year int
)
USING PARQUET
PARTITION BY (Year)
OPTIONS (
PATH 'abfss://...'
)

some_job.py[第二个定义]

def run():
df = spark.read.table('input_table')  # 500 columns
df = transorm(df)
# this logic should be in `transform`, but anycase it should be
df = df.select(
'Id', 'Year', F.col('Value').cast(StringType()).alias('Value')  # actually another schema definition: you have to enumerate all output columns
)
df.write.saveAsTable('some_table')

testrongome_job.py[第三定义]

def test_some_job(spark):
output_schema = ...  # another definition
expected = spark.createDataFrame([...], output_schema)

选项2:在代码中只保留一个定义(StructType(

动态生成模式是可能的。这种方法的好处是简单性和在一个地方定义模式你看到缺点了吗

def run(input: Table, output: Table):
df = spark.read.table(input.name)
df = transform(df)
save(df, output)    
def save(df: DataFrame, table: Table): 
df 
.select(table.schema.fieldNames()) 
.write 
.partitionBy(table.partition_by) 
.option('path', table.path) 
.saveAsTable(table.name)
# In case table doesn't exists, Databricks will automatically generate table definition

class Table(NamedTuple):
name: str
path: str
partition_by: List[str]
schema: StructType

让我先提出几点,然后提出建议。

  1. 数据的寿命比代码长得多
  2. 上面描述的代码是创建&写入数据时,还有读取和使用需要考虑的数据的代码
  3. 还有第三个选项,将数据的定义(模式(与数据一起存储。通常被称为"自我描述格式">
  4. 数据的结构可能会随着时间的推移而变化
  5. 此问题标记有databricksaws-glue
  6. Parquet是在一个文件一个文件的基础上自我描述的
  7. DeltaLake表使用镶木地板数据文件,但还将模式嵌入到事务日志中,从而对整个表和模式进行版本控制
  8. 数据需要由广泛的工具生态系统使用,因此数据需要是可发现的,模式不应锁定在一个计算引擎中

推荐:

  1. 以开放格式存储带有数据的架构
  2. 使用DeltaLake格式(结合Parquet和事务日志(
  3. USING PARQUET更改为USING DELTA
  4. 将您的元存储指向AWS Glue Catalog,Glue Catalog将存储表名和位置
  5. 使用者将从DeltaLake表事务日志中解析架构
  6. 模式可以随着编写器代码的发展而发展

结果:

  1. 您的编写器创建模式,并可以选择性地演化模式
  2. 所有使用者都会在DeltaLake中找到架构(与表版本配对((具体为_Delta_log目录(

在我的公司,我们有一个非常小的团队,所以我们构建了一个基于C#模板的生成器,它从SQL Server数据库中读取信息并生成我们所有的笔记本。为我们的整个系统生成DDL模式和处理代码所需的所有信息都在该数据库中。我们现在唯一手动编码的是Dims和Facts的加载过程的一部分。所有的锅炉板代码都被抽象掉了。对于新的表,我们进入元数据库,输入新的表和列信息并运行生成器。这会导致您在生成的代码中所说的重复,但现在我们只是维护元数据库信息,而不必找到所有需要更新的地方。如果你已经建立了一个系统,这种方法将很难适应,而且说服高层管理层可能是一个挑战,因为前面还有很多开发工作。然而,如果你从零开始,就如何使其通用化,你将获得无与伦比的解决问题和稳定平台的能力。我在野外见过的唯一一款能够在大数据领域做类似事情的产品是Wherescape,如果我没记错的话,它每年每个座位3.5万美元,非常昂贵。所以,如果你的口袋很深,我强烈建议你去看看。[https://www.wherescape.com/][1]可能还有其他人,但这是我所知道的唯一一个。

举几个例子说明这种方法是如何带来好处的。

  1. 我们自己和另一个有两名开发人员,我们能够在4个月内将130个staging和40个Dim and Facts从U-SQL Datalake Analytics完全切换到Databricks。在我们前进的过程中切换出每一个生成的过程。

  2. 比方说,我们在加载暂存表时发现了处理问题,我们更新了流程模板,重新生成了笔记本并重新部署。现在更新了所有130张表的流程,这是日常工作的一半,否则可能需要数周的时间来修复和测试。

最新更新