有没有办法查看Calcite JDBC执行的物理SQL?
Is there any way to view the physical SQLs executed by Calcite JDBC?
最近在研究Apache Calcite,现在我可以通过JDBC使用explain plan for
查看逻辑计划,我想知道如何查看物理sql计划执行?由于物理sql代可能存在bug,所以我需要确保正确性。
val connection = DriverManager.getConnection("jdbc:calcite:")
val calciteConnection = connection.asInstanceOf[CalciteConnection]
val rootSchema = calciteConnection.getRootSchema()
val dsInsightUser = JdbcSchema.dataSource("jdbc:mysql://localhost:13306/insight?useSSL=false&serverTimezone=UTC", "com.mysql.jdbc.Driver", "insight_admin","xxxxxx")
val dsPerm = JdbcSchema.dataSource("jdbc:mysql://localhost:13307/permission?useSSL=false&serverTimezone=UTC", "com.mysql.jdbc.Driver", "perm_admin", "xxxxxx")
rootSchema.add("insight_user", JdbcSchema.create(rootSchema, "insight_user", dsInsightUser, null, null))
rootSchema.add("perm", JdbcSchema.create(rootSchema, "perm", dsPerm, null, null))
val stmt = connection.createStatement()
val rs = stmt.executeQuery("""explain plan for select "perm"."user_table".* from "perm"."user_table" join "insight_user"."user_tab" on "perm"."user_table"."id"="insight_user"."user_tab"."id" """)
val metaData = rs.getMetaData()
while(rs.next()) {
for(i <- 1 to metaData.getColumnCount) printf("%s ", rs.getObject(i))
println()
}
结果是
EnumerableCalc(expr#0..3=[{inputs}], proj#0..2=[{exprs}])
EnumerableHashJoin(condition=[=([=12=], )], joinType=[inner])
JdbcToEnumerableConverter
JdbcTableScan(table=[[perm, user_table]])
JdbcToEnumerableConverter
JdbcProject(id=[[=12=]])
JdbcTableScan(table=[[insight_user, user_tab]])
可以通过设置 calcite.debug=true
系统 属性 查看生成的 SQL 查询。发生这种情况的确切位置在 JdbcToEnumerableConverter。由于这是在执行查询期间发生的,因此您必须删除 "explain plan for"
来自 stmt.executeQuery
.
请注意,通过将调试模式设置为 true,您将收到许多其他消息以及有关生成代码的其他信息。
有一个 Calcite Hook,Hook.QUERY_PLAN
由 JDBC 查询字符串触发。来自 source:
/** Called with a query that has been generated to send to a back-end system.
* The query might be a SQL string (for the JDBC adapter), a list of Mongo
* pipeline expressions (for the MongoDB adapter), et cetera. */
QUERY_PLAN;
您可以注册一个侦听器来记录任何查询字符串,例如 Java:
Hook.QUERY_PLAN.add((Consumer<String>) s -> LOG.info("Query sent over JDBC:\n" + s));
最近在研究Apache Calcite,现在我可以通过JDBC使用explain plan for
查看逻辑计划,我想知道如何查看物理sql计划执行?由于物理sql代可能存在bug,所以我需要确保正确性。
val connection = DriverManager.getConnection("jdbc:calcite:")
val calciteConnection = connection.asInstanceOf[CalciteConnection]
val rootSchema = calciteConnection.getRootSchema()
val dsInsightUser = JdbcSchema.dataSource("jdbc:mysql://localhost:13306/insight?useSSL=false&serverTimezone=UTC", "com.mysql.jdbc.Driver", "insight_admin","xxxxxx")
val dsPerm = JdbcSchema.dataSource("jdbc:mysql://localhost:13307/permission?useSSL=false&serverTimezone=UTC", "com.mysql.jdbc.Driver", "perm_admin", "xxxxxx")
rootSchema.add("insight_user", JdbcSchema.create(rootSchema, "insight_user", dsInsightUser, null, null))
rootSchema.add("perm", JdbcSchema.create(rootSchema, "perm", dsPerm, null, null))
val stmt = connection.createStatement()
val rs = stmt.executeQuery("""explain plan for select "perm"."user_table".* from "perm"."user_table" join "insight_user"."user_tab" on "perm"."user_table"."id"="insight_user"."user_tab"."id" """)
val metaData = rs.getMetaData()
while(rs.next()) {
for(i <- 1 to metaData.getColumnCount) printf("%s ", rs.getObject(i))
println()
}
结果是
EnumerableCalc(expr#0..3=[{inputs}], proj#0..2=[{exprs}])
EnumerableHashJoin(condition=[=([=12=], )], joinType=[inner])
JdbcToEnumerableConverter
JdbcTableScan(table=[[perm, user_table]])
JdbcToEnumerableConverter
JdbcProject(id=[[=12=]])
JdbcTableScan(table=[[insight_user, user_tab]])
可以通过设置 calcite.debug=true
系统 属性 查看生成的 SQL 查询。发生这种情况的确切位置在 JdbcToEnumerableConverter。由于这是在执行查询期间发生的,因此您必须删除 "explain plan for"
来自 stmt.executeQuery
.
请注意,通过将调试模式设置为 true,您将收到许多其他消息以及有关生成代码的其他信息。
有一个 Calcite Hook,Hook.QUERY_PLAN
由 JDBC 查询字符串触发。来自 source:
/** Called with a query that has been generated to send to a back-end system.
* The query might be a SQL string (for the JDBC adapter), a list of Mongo
* pipeline expressions (for the MongoDB adapter), et cetera. */
QUERY_PLAN;
您可以注册一个侦听器来记录任何查询字符串,例如 Java:
Hook.QUERY_PLAN.add((Consumer<String>) s -> LOG.info("Query sent over JDBC:\n" + s));