Skip to content

Performance regression in 2.2.222 #3883

@andreitokar

Description

@andreitokar

Threre is a complaint in H2 user group, which I can confirm.
I boiled the problem down to that commit, but have no idea yet about why/how it gets slower.
When this commit gets reverted, performance goes back to 2.2.220 level, but I was not able to find a missing conversion from synchronized to ReenterantLock.
It seems like not everyone is able to confirm it, so it could be OS / JDK specific. I am on Linux / JDK11.
My suspicion that it changes plan somehow, and not taking some optimized path?

Anyway, that's the test case:

public class H2PerformanceTest {
    private final static Logger LOGGER = Logger.getLogger(H2PerformanceTest.class.getName());

    public static void main(String[] args) throws ClassNotFoundException {
        String[] sqlStr = {
                "CREATE TABLE IF NOT EXISTS A (number VARCHAR(128) not NULL, intent INT not NULL, objID VARCHAR(30) not NULL, objType SMALLINT  not NULL, PRIMARY KEY (number,intent,objID,objType));",
                "CREATE INDEX IF NOT EXISTS A_IDX ON A(objType,objID,intent);",
                "CREATE INDEX IF NOT EXISTS A_type_IDX ON A (objType);",

                "DROP TABLE IF EXISTS B; ",
                "CREATE TABLE IF NOT EXISTS B (number VARCHAR(128) not NULL, intent INT not NULL, objID VARCHAR(30) not NULL, objType SMALLINT  not NULL, PRIMARY KEY (number,intent,objID,objType));",
                "CREATE INDEX IF NOT EXISTS B_IDX ON B(objType,objID,intent);",

                "DELETE FROM A T WHERE EXISTS (SELECT NULL from A S WHERE T.objID=S.objID AND T.objType=S.objType AND T.intent=S.intent AND T.number<>S.number);",
                "MERGE INTO A T USING (SELECT * FROM B) AS S ON T.objID=S.objID AND T.objType=S.objType AND T.intent=S.intent AND T.number=S.number WHEN NOT MATCHED THEN INSERT (objID, objType, number, intent) VALUES (S.objID, S.objType, S.number, S.intent);",
                "DROP TABLE B CASCADE"

        };

        Class.forName("org.h2.Driver");
        try (Connection conn = DriverManager.getConnection(
                "jdbc:h2:mem:",
                "SA",
                ""
        ); Statement statement = conn.createStatement()) {
            statement.execute(sqlStr[0]);
            statement.execute(sqlStr[1]);
            statement.execute(sqlStr[2]);

            for (int loop = 0, number = 0; loop < 300; ++loop) {
                statement.execute(sqlStr[3]);
                statement.execute(sqlStr[4]);
                statement.execute(sqlStr[5]);

                for (int i = 0; i < 100; ++i) {
                    ++number;
                    statement.execute("MERGE INTO B (number,intent,objID,objType) VALUES ('"
                                      + number
                                      + "',1, '"
                                      + number
                                      + "', 1);");
                }
                statement.execute(sqlStr[6]);
                statement.execute(sqlStr[7]);
                statement.execute(sqlStr[8]);

                LOGGER.log(Level.INFO, "loop = " + loop);
            }
        } catch (Exception ex) {
            LOGGER.log(Level.SEVERE, "Error in loop", ex);
        }
    }
}

My results:
2.2.220 ~ 14 sec, linear trough the test.
2.2.222 ~ 150 sec with gradual non-linear slowdown (but it's not memory)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions