51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Impala JDBC/ODBC driver返回不完整数据的解决办法

01


背景

用户在升级到CDP或Impala-3.4后,可能遇到JDBC/ODBC driver返回不完整数据的情况。比如实际查询结果有100行,但返回90行就结束了,每次的结果不一定相同,只有在时长超过10秒的查询会出现。这可能是遇到了JDBC/ODBC driver的bug,可以尝试以下两种方式解决:

  • Query Option 里 set fetch_rows_timeout_ms=0

  • 升级driver版本,JDBC driver版本至少要到2.6.20,ODBC driver版本至少要到2.6.12

如果以上方法有效,就跟我们要讲的这个bug有关。
02


客户端流程 客户端与Coordinator交互有两种协议:beeswax和hs2协议。它们都是基于Thrift实现的,各种接口基本上能一一对应。对于一个查询的执行,客户端的请求流程如下,以beeswax协议为例: 对应的HS2 RPC如下:

| beeswax | hs2 | |:--------------:|:----------------:| | executeAndWait | ExecuteStatement | | fetch | FetchResults | | close | CloseOperation |

问题出在finish的判定上。
03


Finish判定 Beeswax 的 fetch RPC 和 HS2 的 FetchResults RPC 的返回类型定义如下:

// beeswax result
struct Results {
  // If set, data is valid.  Otherwise, results aren't ready yet.
  1: bool ready,
  // Columns for the results
  2: list<string> columns,
  // A set of results               
  3: list<string> data,
  // The starting row of the results
  4: i64 start_row,
  // Whether there are more results to fetch
  5: bool has_more
}

// hs2 result
struct TFetchResultsResp {
  1: required TStatus status

  // TRUE if there are more rows left to fetch from the server.
  2: optional bool hasMoreRows

  // The rowset. This is optional so that we have the
  // option in the future of adding alternate formats for
  // representing result set data, e.g. delimited strings,
  // binary encoded, etc.
  3: optional TRowSet results
}

它们除了返回一组数据,还返回一个bool值(has_more、hasMoreRows)标记是否还有更多的数据。理论上用这个值来判断是否要结束就可以了,但如果客户端偷懒,只判断返回的数据是否为空,是否也可行呢? 04


流水线执行
Impala使用MPP架构设计,区别于MR、Spark、Tez等BSP模式的一大特点是流水线式执行。查询计划由多段流水线组成,查询的执行由流水线的消费者驱动。客户端就是最后一条流水线的消费者。 客户端开始获取结果时,流水线的另一端可能还在执行。比如一个简单的 select ... from tableA where col = 'A' 查询,ScanNode是分布式执行的,每个ScanNode内部也是流式执行的,每次读一片数据过滤完就可以返回结果。因此客户端可以开始拉取数据时(即 "Rows Available" 状态),并不代表所有结果都已经生成了。有可能第一批数据被拉取完后,要过10秒或更长的时间才能拉取下一批数据。 05


IMPALA-7312后 fetch RPC 的变化

在 IMPALA-7312 之前,fetch请求是阻塞式的,会卡住直到有查询结果可返回为止。因此 fetch 返回的结果都有数据。直到所有结果都被拉取完时,fetch 才会返回空集。虽然这是老版本Impala的表现,但这并不是一个定义好的行为,实际上还得用 has_more/hasMoreRows 标记来判定是否还有结果没拉取。 IMPALA-7312 引入了 fetch_rows_timeout_ms 这个查询选项,给 fetch 请求加了超时。服务器端(即coordinator)会在超时前返回一个结果,该结果可能为空,但has_more/hasMoreRows 会标记查询结果是否全返回了。如果客户端没有判断 has_more/hasMoreRows,只看 fetch 返回的结果集是否为空,就可能误判结束标志。此时只能设 fetch_rows_timeout_ms = 0 来绕过这个超时机制。 由于 impala-shell 一直是有判定 has_more / hasMoreRows 这个域的,所以不受影响。这个问题主要出在 Impala JDBC/ODBC driver上。 06


升级Driver 这个问题在 Impala JDBC/ODBC 的 Release Note 中都有提及,如 JDBC driver 2.6.20: Released 2020-12-18

The following issues have been resolved in Simba Impala JDBC Driver 2.6.20.

  • [00265194][IMPJ-606] When the server returns 0 rows, the driver stops fetching results.

ODBC driver 2.6.12:

Released 2020-12-23
The following issue has been resolved in Cloudera ODBC Driver for Impala 2.6.12.

  • [IMP-806][00265194] When the server returns 0 rows, the driver stops fetching results.

07


总结 Impala JDBC/ODBC driver 使用了未定义的方式来判定查询结束,该方式在 IMPALA-7312 之后不可行。因此解决办法是关闭 IMPALA-7312 引入的超时机制(即 set fetch_rows_timeout_ms = 0)或者升级 driver 版本,JDBC driver版本至少要到2.6.20,ODBC driver版本至少要到2.6.12。

关注Impala 公众号,及时获取更多Impala资讯

赞(4)
未经允许不得转载:工具盒子 » Impala JDBC/ODBC driver返回不完整数据的解决办法