【问题标题】:Extremely slow Apache Drill Query using Oracle jdbc使用 Oracle jdbc 的 Apache Drill Query 非常慢
【发布时间】:2017-06-08 11:19:15
【问题描述】:

我已经成功地将 Apache Drill(最新 1.9)与 Oracle 的 JDBC 客户端(来自 oracle 的最新 ojdbc7.jar)设置为存储插件:

{
  "type": "jdbc",
  "driver": "oracle.jdbc.driver.OracleDriver",
  "url": "jdbc:oracle:thin:@server:1521/myservicename",
  "username": "TEST_USER",
  "password": "password",
  "enabled": true
}

我可以进行查询,但即使是最简单的事情也需要几分钟才能执行。 查询单行表需要 78 秒。 仅设置默认架构需要一分钟:

0: jdbc:drill:zk=local> use oracle.TEST_USER
. . . . . . . . . . . > ;
+-------+-------------------------------------------------+
|  ok   |                     summary                     |
+-------+-------------------------------------------------+
| true  | Default schema changed to [oracle.TEST_USER]  |
+-------+-------------------------------------------------+
1 row selected (77,5 seconds)

但是我已经用一个简单的 hello-world 风格的 java 应用程序进行了测试,具有相同连接字符串的连接工作得非常好,全表获取时间大约为 0.1 秒。

jdbc:oracle:thin:@server:1521/myservicename

我已经在 Ubuntu 和 Mac 上进行了测试,还尝试为 java 设置随机源,因为其他答案指出潜在的性能问题:

export DRILL_JAVA_OPTS="$DRILL_JAVA_OPTS -Djava.security.egd=file:/dev/./urandom"

这里发生了什么?这是一个已知问题还是有一些解决方法?

我使用过钻孔嵌入。

【问题讨论】:

  • 激活 Oracle 10046 跟踪以查看数据库中经过的时间。

标签: java oracle jdbc apache-drill


【解决方案1】:

我能够找到这个问题的根本原因。

问题不是查询速度慢,而是 Drill 的元数据查询中的非最优预取策略。 在我的例子中,数据库很大,每一个数百个表都有数千个模式(oracle 用户)。并且 oracles 默认的 fetchsize 是 10,导致数百次 DB 往返。

每个 Apache Drill JDBC 查询都在检查元数据。

内部Apache Drill: JdbcStoragePlugin.java#L351

java.sql.DatabaseMetaData.getSchemas()

内部Apache Calcite (Drill dependency): JdbcMeta.java#L323

java.sql.DatabaseMetaData.getTables(...)

这两个部分都不会覆盖任何默认的 fetchsize,并且通过 wireshark,我可以逐个地观察包,每个包只有 10 行。 (数据库服务器的延迟非常高,因为它位于其他地方)

我已经通过手动调用 setFetchSize 重新编译了 Apache Drill,这大大缩短了响应时间。到目前为止,我还没有修补 Calcite,但可能也会这样做。

总的来说,我认为在获取元数据时,还应考虑编写高性能 JDBC 代码的常规步骤,因为现实世界的场景很容易以更大的元数据结束(例如,超过 10 个表或模式) 另一个想法是缓存,但我没有看到在 Drill 的 JDBC 存储插件中进行任何元数据缓存。

【讨论】:

  • 嗨,Thomas,您能分享一下需要在 JdbcStoragePlugin.java 中添加的确切 setFetchSize 代码吗?
  • 嗨,Thomas,你能分享一下补丁吗
  • 我的 Drill-env.sh 中有 export DRILLBIT_JAVA_OPTS="$DRILLBIT_JAVA_OPTS -Doracle.jdbc.defaultRowPrefetch=50000"
【解决方案2】:

对于那些有同样问题并试图找到答案的人。

我更新了 oracle jar 文件 /oracle/jdbc/defaultConnectionProperties.properties

并添加 oracle.jdbc.defaultRowPrefetch=200

我使用7zip打开和编辑文件内容

注意:您需要为您的案例找到最佳的 rowPrefetch

我阅读this 是为了给我一个想法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-08
    • 1970-01-01
    • 2013-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多