重复的语句
适用于 ✅ 开源版 ✅ 专业版 ✅ 企业版
处理此事件的 SPI 方法是 repeatedStatements()
有时,除了连续多次重复相同的(或相似的,参见重复语句)语句之外别无选择,但通常,这表明您的查询可以重写,并且重复的语句实际上应该连接到更大的查询中。
为什么这不好?
这个问题通常被称为 N+1 问题。加载父实体(通常由 ORM 加载),并延迟加载其子实体。不幸的是,存在多个父实例,因此对于每个父实例,我们现在都在加载一组子实例,从而导致许多查询。此诊断会检测在同一连接上是否重复执行相同的语句,即使它不是完全相同的语句。
这里给出了一个例子
// A custom DiagnosticsListener SPI implementation class RepeatedStatement implements DiagnosticsListener { @Override public void repeatedStatements(DiagnosticsContext ctx) { // The statement that is being executed and which has duplicates System.out.println("Actual statement: " + ctx.actualStatement()); // A normalised version of the actual statement, which is shared by all duplicates // This statement has "normal" whitespace, bind variables, IN-lists, etc. System.out.println("Normalised statement: " + ctx.normalisedStatement()); // All the duplicate actual statements that have produced the same normalised // statement in the recent past. System.out.println("Repeated statements: " + ctx.repeatedStatements()); } }
然后
// Configuration is configured with the target DataSource, SQLDialect, etc. for instance Oracle. try (Connection c = DSL.using(configuration.derive(new RepeatedStatement())) .diagnosticsConnection(); Statement s1 = c.createStatement(); ResultSet a = s1.executeQuery("SELECT id FROM author WHERE first_name LIKE 'A%'")) { while (a.next()) { int id = a.getInt(1); // This query is run once for every author, when we could have joined the author table try (PreparedStatement s2 = c.prepareStatement("SELECT title FROM book WHERE author_id = ?")) { s2.setInt(1, id); try (ResultSet b = s2.executeQuery()) { while (b.next()) System.out.println("ID: " + id + ", title: " + b.getString(1)); } } } }
与检测重复语句不同,重复语句统计信息仅在本地执行,对于单个 JDBC 连接,或者如果可能,对于事务。不同事务中的重复语句通常并不表示存在问题。
反馈
您对此页面有任何反馈吗? 我们很乐意听到!