Go语言使用rows.Next()读取Oracle大字段数据时卡顿问题求助
Go读取Oracle大字段时rows.Next()卡顿/卡死的解决办法
问题根源
你遇到的问题是github.com/sijms/go-ora/v2驱动默认行预取数为25行,当结果包含大体积的TEXT、SOLUTION字段时,每次预取的数据包过大,导致网络传输和内存处理瓶颈,表现为每读25行就停顿,最终因资源耗尽卡死。去掉大字段后数据量骤减,速度自然恢复正常。
可行解决方案
1. 调大预取行数
直接修改查询的预取大小,减少网络交互次数,这是最直接的解决办法。go-ora支持通过FetchSize选项设置预取行数,建议根据网络情况调整为1000-5000行。
2. 分批查询数据
将40万条数据拆分为小批次(比如每次查1万条),避免一次性加载大量大字段数据到内存,同时降低Oracle服务器压力。
3. 分段读取大字段(针对超大型文本)
如果TEXT/SOLUTION字段体积特别大(如超过10MB),可使用Oracle的LOB分段读取功能,不过go-ora需要额外处理,适合极端场景。
代码修改示例
方案1:设置FetchSize
修改GetHrTicketsFromOra函数,通过QueryContext指定预取大小:
import ( "context" "database/sql" "log" "github.com/sijms/go-ora/v2" ) func GetHrTicketsFromOra() (*sql.Rows, error) { // 设置预取行数为1000,可根据实际情况调整 fetchOpt := go-ora.FetchSize(1000) rows, err := oraDB.QueryContext(context.Background(), "select id,STATE_ID,REMEDY_ID,HEADER,CREATE_DATE,TEXT,SOLUTION,SOLUTION_USER_LOGIN,LAST_SOLUTION_DATE from TICKET where SOLUTION_GROUP_ID = 5549", fetchOpt, ) if err != nil { log.Println("Error while getting rows from Ora:", err) return nil, err } log.Println("Finished legacy tickets export") return rows, nil }
方案2:分批查询
按ID分段拉取数据,避免一次性处理过大结果集:
func GetHrTicketsBatch(batchSize int) ([]util.OraTicket, error) { var allTickets []util.OraTicket lastID := 0 for { rows, err := oraDB.Query(` select id,STATE_ID,REMEDY_ID,HEADER,CREATE_DATE,TEXT,SOLUTION,SOLUTION_USER_LOGIN,LAST_SOLUTION_DATE from TICKET where SOLUTION_GROUP_ID = 5549 and id > ? order by id fetch next ? rows only`, lastID, batchSize, ) if err != nil { return nil, err } ticketCount := 0 for rows.Next() { ot := util.OraTicket{} err := rows.Scan(&ot.ID, &ot.StateId, &ot.RemedyId, &ot.Header, &ot.CreateDate, &ot.Text, &ot.Solution, &ot.SolutionUserLogin, &ot.LastSolutionDate) if err != nil { rows.Close() return nil, err } allTickets = append(allTickets, ot) lastID = ot.ID ticketCount++ } rows.Close() if ticketCount < batchSize { break // 无更多数据 } } return allTickets, nil }
额外优化点
- 删除
ConvertRows中的log.Println("Reading the ticket"),频繁打日志会严重拖慢读取速度。 - 给转换通道添加缓冲:例如
c := make(chan util.ArchTicket, 200),避免PostgreSQL插入速度慢阻塞Oracle数据读取。
内容的提问来源于stack exchange,提问作者Undesired
相关产品推荐
相关产品推荐

