我已经使用Oracle的JDBC客户端(来自oracle的最新ojdbc7.jar)作为存储插件成功设置了Apache Drill(最新1.9):
{
"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-style 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"
这里发生了什么?这是一个已知问题还是有一些解决方法?
我用过钻头嵌入的。
最佳答案
我能够找到此问题的根本原因。
问题不是查询速度慢,而是Drill的元数据查询中的非最佳预取策略。
在我的情况下,数据库非常庞大,每个表都有数百个架构(oracle用户)。 oracle默认的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,这大大缩短了响应时间。到目前为止,我还没有补丁方解石,但也可能会做。
总的来说,我认为在获取元数据时,还应考虑编写高性能JDBC代码的常规步骤,因为现实世界中的场景很容易以较大的元数据(例如,超过10个表或模式)结尾
另一个想法是缓存,但是我没有看到Drill的JDBC存储插件中进行任何元数据缓存。