Hello,

I have similar H2 1.4 MVCC performance problems with parallel selects.

In attached test case a test table is created with 10k records.
Then 4 threads are started, each executing 1000 consecutive selects, n-th 
select returns n records.

If a test is started as is, with MULTI_THREADED=TRUE (MVCC true by 
default), it takes approx 2s on my machine.
If ';MV_STORE=FALSE;MVCC=FALSE' is appended to dbUrl, test takes 0,5s.
Taking in account 4 parallel threads, the MVCC version is practically 
non-parallel.

Thread dump during parallel read shows that one of the 4 threads locks on 
'undoLog', others are waiting for that same lock.

Tested on 1.4.194 and 1.4.195.

In a real case with 50 threads this results in performance similar as in 3 
threads; 15-20 times slower with MVCC. And I need MVCC.

Otherwise you just have to love this H2, its simply great. :)

David.

-- 
You received this message because you are subscribed to the Google Groups "H2 
Database" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/h2-database.
For more options, visit https://groups.google.com/d/optout.
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author David Vidrih
 */
public class H214MvccTest
{
    public static void main(String... args) throws Exception
    {
        String url = "jdbc:h2:mem:H214MvccTest;MULTI_THREADED=TRUE"; // MVCC version
        //String url = "jdbc:h2:mem:H214MvccTest;MULTI_THREADED=TRUE;MV_STORE=FALSE;MVCC=FALSE"; // PageStore version

        Class.forName("org.h2.Driver");
        Connection con = DriverManager.getConnection(url, "sa", "");
        con.setAutoCommit(false);

        // create table, insert test data
        executeUpdate(con, "create table test(id number(19), str varchar2(4000), primary key (id))");
        for (int i = 0; i < 10000; i++)
            executeUpdate(con, "insert into test (id, str) values (" + i + ", '" + i + "')");
        con.commit();

        // read in parallel
        int threadCount = 4;
        List<TestReader> testReaders = new ArrayList<>();
        for (int threadNo = 0; threadNo < threadCount; threadNo++)
            testReaders.add(new TestReader(threadNo));

        ExecutorService threadPool = Executors.newFixedThreadPool(threadCount);
        long startMillis = System.currentTimeMillis();
        threadPool.invokeAll(testReaders);
        long duration = System.currentTimeMillis() - startMillis;
        threadPool.shutdown();
        System.out.println("duration:" + duration);

        con.close();
        //System.exit(0);
    }

    private static void executeUpdate(Connection con, String sql) throws SQLException
    {
        Statement stmt = con.createStatement();
        stmt.executeUpdate(sql);
        stmt.close();
    }

    public static class TestReader implements Callable<Object>
    {
        private int id;

        public TestReader(int id)
        {
            this.id = id;
        }

        @Override
        public Object call() throws Exception
        {
            try
            {
                Connection con = DriverManager.getConnection("jdbc:h2:mem:H214MvccTest", "sa", "");
                con.setAutoCommit(false);
                PreparedStatement ps = con.prepareStatement("select id, str from test where id <= ?");
                for (int readNo = 0; readNo < 1000; readNo++)
                {
                    ps.clearParameters();
                    ps.setLong(1, readNo);
                    ResultSet rs = ps.executeQuery();
                    while (rs.next())
                    {
                        long id = rs.getLong(1);
                        String str = rs.getString(2);
                    }
                    rs.close();
                }
                ps.close();
                con.commit();
                con.close();
            }
            catch (SQLException e)
            {
                e.printStackTrace();
                throw e;
            }
            System.out.println("TestReader " + id + " finished.");
            return null;
        }
    }
}

Reply via email to