最终,我想从Vertica数据库中获取数据到Spark,训练机器学习模型,进行预测,并将这些预测存储到另一个Vertica数据库中。
当前的问题是确定流程最后部分的瓶颈:在Spark中存储Vertica DB中的值。在Vertica DB中存储63k行数据大约需要38分钟。相比之下,当我将相同的数据从Spark传输到 MySQL数据库时,需要 10秒。
我不知道为什么差异如此巨大。
我分别为Vertica和MySQL连接提供了名为VerticaContext和MySQLContext的类。两个类都使用SQLContext来使用jdbc格式读取条目。
df = self._sqlContext.read.format('jdbc').options(url=self._jdbcURL, dbtable=subquery).load()
使用jdbc编写。
df.write.jdbc(self._jdbcURL, table_name, save_mode)
除了写入不同的目标数据库之外,这两个类之间没有区别。我很困惑为什么保存表格所需的时间差别很大。是因为两个不同数据库之间硬件的固有差异吗?
答案 0 :(得分:1)
我想出了另一种解决方案。在我深入研究之前,我将解释我发现的内容以及为什么我认为对Vertica DB的保存速度很慢。
我的解决方案:
有documentation表示COPY命令(带有“DIRECT”关键字)是将大量数据加载到数据库的最有效方法。由于我正在寻找python解决方案,我使用Uber的vertica-python package,它允许我与Vertica DB建立连接并发送Vertica命令来执行。
我想利用COPY命令的效率,但数据位于Vertica群集之外的某个位置。我需要将Spark集群中的数据发送到Vertica DB。幸运的是,有一种方法可以从HDFS中做到这一点(见here)。我决定将数据帧转换为csv文件并将其保存在HDFS上。然后我将COPY命令发送到Vertica DB以从HDFS获取文件。
我的代码在下面(假设我有一个存储pyspark数据帧的变量。让我们称之为'df'):
import vertica_python as VertPy
df.toPandas().to_csv(hdfs_table_absolute_filepath, header=False, index=False)
conn_info = {
'host': ['your-host-here']
'port': [port #],
'user': ['username'],
'password': ['password'],
'database': ['database']
}
conn = VertPy.connect(**conn_info)
cur = conn.cursor()
copy_command = create_copy_command(table_name, hdfs_table_relative_filepath)
cursor.execute(copy_command)
def create_copy_command(table_name, table_filepath):
copy_command = "COPY " + table_name + " SOURCE Hdfs(url='http://hadoop:50070/webhdfs/v1" + table_filepath + "', username='root') DELIMITER ',' DIRECT ABORT ON ERROR"
return copy_command