在R中对远程DB2数据库执行collect()时出现异常错误
问题:DB2远程表执行collect()时出现内存溢出及方法不存在错误
场景说明
通过RJDBC连接DB2远程表,使用dplyr的filter()等操作可正常运行,但执行collect()将数据拉取到本地时触发报错。
连接代码
driver <- JDBC("com.ibm.db2.jcc.DB2Driver", "C:/Program Files/ibm/IBM DATA SERVER DRIVER/java/db2jcc4.jar") password conn <- dbConnect(driver, "jdbc:db2://wwtc.worldpac.com/S1013FCD", "username", "pw") prg = tbl(conn, in_schema("ASDFLIB01", "SROPRG"))
数据处理代码及报错信息
执行以下代码到collect()时出错:
prg3 <- prg2 %>% select(PGPRDC, PGAGRP, PGCAT1, PGCAT2, PGCAT3, PGCAT4, PGCDAT, PGRFDT, PGRTDT, PGSUPP, PGSHNO, PGDESC, PGSUPC, PGRESP, PGAPCO, PGA6CO, #second avg cost? PGASCO, PGBCOS, PGFCOS, PGHNDV, PGMULT, PGBGAP, everything()) %>% rename(prod_code = PGPRDC, prod_acct_grp = PGAGRP, cat1 = PGCAT1, cat2 = PGCAT2, cat3 = PGCAT3, cat4 = PGCAT4, prod_creation_date = PGCDAT, prod_replace_from_date = PGRFDT, prod_replace_to_date = PGRTDT, supplier_number = PGSUPP, prod_short_name = PGSHNO, prod_desc = PGDESC, supercede_yn = PGSUPC, responible = PGRESP, unit = PGUNIT, vehicle_make = PGPGRP, lot = PGBATC, lead_time = PGLEAD, structure_code = PGSTRC, override_price_yn = PGOVDC, backlog_code_yn = PGBALC, avg_purch_cost = PGAPCO, standard_cost = PGASCO, base_cost = PGBCOS, future_cost = PGFCOS, handling_cost = PGHNDV, prod_weight = PGWEIG, car_line_ABC = PGABCC, car_line_popularity = PGROPC, company_wide_ABC = PGEOQC, image_crit_core = PGSECT, con_ctr_init_qty = PGPQTY, pack_size = PGSIZE, selling_increment = PGSINC, avg_purch_cost2 = PGA6CO, base_cost_multiplier = PGMULT, avg_and_base_cost_gap = PGBGAP, country_code = PGCOUN) %>% collect()
报错信息:
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "Timer-0" Error in ._jobjRef_dollar(x[["jobj"]], name) : no field, method or inner class called 'use_cli_format'
当前环境
- R 4.2.2
- tidyverse 1.3.2
- RJDBC 0.2-10
- dbplyr 2.3.0
已多次重启R会话并更新本地Java版本,问题仍存在。
解决思路与步骤
1. 解决Java内存溢出问题
- 增加Java堆内存:在R启动前设置Java参数,比如修改R快捷方式的目标为
"C:\Program Files\R\R-4.2.2\bin\Rgui.exe" -Xmx4g(根据机器内存调整,例如8GB内存可设-Xmx8g);也可在R中先执行options(java.parameters = "-Xmx4g"),再重新建立JDBC连接。 - 减少单次拉取数据量:
- 先用
filter()筛选出所需数据子集,再执行collect(); - 用
slice_sample(n = 1000)或head(1000)测试小数据量能否正常拉取; - 分批次读取数据,例如按某个字段分段查询后合并。
- 先用
2. 处理use_cli_format方法不存在错误
- 调整dbplyr版本:尝试降级dbplyr到2.2.0版本,或升级到最新稳定版,因为该方法可能是dbplyr版本变更后新增,与旧版RJDBC存在兼容性问题。执行命令:
# 降级版本 install.packages("dbplyr", version = "2.2.0", repos = "https://cran.r-project.org") # 或升级到最新版 install.packages("dbplyr") - 绕过dbplyr封装直接执行SQL:先生成查询语句,再用
dbGetQuery()直接从数据库获取数据:# 生成SQL查询语句 query <- prg2 %>% select(...) %>% rename(...) %>% show_query() # 执行查询并获取数据 prg3 <- dbGetQuery(conn, as.character(query))
3. 其他排查方向
- 检查DB2驱动兼容性:确认
db2jcc4.jar的版本与DB2服务器版本匹配,尝试更换为对应版本的驱动文件。 - 排查字段类型问题:暂时排除部分可能存在特殊类型的字段,测试
collect()是否正常,逐步定位是否有字段导致转换异常。
内容的提问来源于stack exchange,提问作者horton.papa
相关产品推荐
相关产品推荐

