我有以下任务:
我正在使用以下代码(或多或少):
def connect_to_oracle_db(spark_session, db_query):
return spark_session.read \
.format("jdbc") \
.option("url", "jdbc:oracle:thin:@//<host>:<port>/<srvice_name") \
.option("user", "<user>") \
.option("password", "<pass>") \
.option("dbtable", db_query) \
.option("driver", "oracle.jdbc.driver.OracleDriver")
def run(self):
all_schemes = <list of all available schemes>
for str_schema in all_schemes:
db_query = "(Select * from " + str_schema + ".TABLE1) TABLE1_DATA"
df_table1 = slef.connect_to_oracle_db(db_query).load()
# process df_table1
大约有300个方案,而且速度很慢,因为每个迭代都会创建并关闭新连接。我想找到一种方法来重用现有连接或以某种方式创建连接池。对我来说似乎无效。
您是否知道如何重用连接或为PySpark创建连接池?
答案 0 :(得分:2)
在像Spark这样的分布式系统中,没有经典意义上的连接池。您必须记住,每个分区可以由不同的物理节点,不同的逻辑容器(如果适用于给定的集群管理器)以及最后的不同的JVM处理。
在这种情况下,连接池并不是真的有帮助。由于Spark用于大量进口,因此单个连接的利用率已经很高。
然而,这里有不同的可见问题(还有可能是其他问题,在您的代码段中并不明显,因为您显示的代码实际上并未获取数据):
您没有配置fetchsize
,因此将使用特定驱动程序的默认设置。对于Oracle it is 10,这完全不适合大规模处理
return spark_session.read
.format("jdbc")
.option("fetchsize", some_reasonable_value)
...
您未配置分区,因此Spark将process all data using only a single partition。您可以在How to optimize partitioning when migrating data from JDBC source?
您已将此建模为一个顺序过程。除非以某种方式在下游组合数据集,否则最好为每个表提交一个单独的作业,然后让scheduler根据可用资源进行优化。
您还可以考虑处理表in parallel in a single application
重申一下-Spark很懒,因此核心问题可能在其他地方,而上面列出的问题可能是次要的。