可用版本: Dev (3.21) | 最新 (3.20) | 3.19 | 3.18 | 3.17 | 3.16 | 3.15 | 3.14 | 3.13 | 3.12 | 3.11

重复的语句

适用于 ✅ 开源版   ✅ 专业版   ✅ 企业版

处理此事件的 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 连接,或者如果可能,对于事务。不同事务中的重复语句通常并不表示存在问题。

反馈

您对此页面有任何反馈吗? 我们很乐意听到!

The jOOQ Logo