codefollower/My-Blog

DB Benchmark

codefollower opened this issue · 2 comments

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Random;
import java.util.concurrent.CountDownLatch;

//运行这个例子要在MySQL和PostgreSQL中存在一个test数据库
public class Benchmark {
    static String url = "jdbc:mysql://localhost:3306/test?user=test&password=test";
    // static String url = "jdbc:postgresql://localhost/test?user=test&password=test";
    static Random random = new Random();
    static CountDownLatch latch;

    public static void main(String[] args) throws Exception {
        benchmark();
    }

    static Connection getConnection() throws Exception {
        return DriverManager.getConnection(url);
    }

    static class MyThread extends Thread {
        Statement stmt;
        Connection conn;
        long read_time;
        long randow_read_time;
        long write_time;
        int start;
        int end;

        MyThread(int start, int count) throws Exception {
            super("MyThread-" + start);
            conn = getConnection();
            stmt = conn.createStatement();
            this.start = start;
            this.end = start + count;
        }

        void write() throws Exception {
            long t1 = System.currentTimeMillis();
            for (int i = start; i < end; i++) {
                String sql = "INSERT INTO test(f1, f2) VALUES(" + i + "," + i * 10 + ")";
                stmt.executeUpdate(sql);
            }

            long t2 = System.currentTimeMillis();
            write_time = t2 - t1;
            System.out.println(getName() + " write end, time=" + write_time + " ms");
        }

        void read(boolean randow) throws Exception {
            long t1 = System.currentTimeMillis();
            for (int i = start; i < end; i++) {
                ResultSet rs;
                if (!randow)
                    rs = stmt.executeQuery("SELECT * FROM test where f1 = " + i);
                else
                    rs = stmt.executeQuery("SELECT * FROM test where f1 = " + random.nextInt(end));
                while (rs.next()) {
                    // System.out.println("f1=" + rs.getInt(1) + " f2=" + rs.getLong(2));
                }
            }

            long t2 = System.currentTimeMillis();

            if (randow)
                randow_read_time = t2 - t1;
            else
                read_time = t2 - t1;
            if (randow)
                System.out.println(getName() + " randow read end, time=" + randow_read_time + " ms");
            else
                System.out.println(getName() + "  read end, time=" + read_time + " ms");
        }

        @Override
        public void run() {
            try {
                write();
                read(false);
                read(true);
                stmt.close();
                conn.close();
                latch.countDown();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    static void benchmark() throws Exception {
        Connection conn = getConnection();
        Statement stmt = conn.createStatement();
        stmt.executeUpdate("DROP TABLE IF EXISTS test");
        stmt.executeUpdate("CREATE TABLE IF NOT EXISTS test (f1 int primary key, f2 real)");
        stmt.close();
        conn.close();

        int threadsCount = Runtime.getRuntime().availableProcessors();
        int loop = 1000;
        latch = new CountDownLatch(threadsCount);

        MyThread[] threads = new MyThread[threadsCount];
        for (int i = 0; i < threadsCount; i++) {
            threads[i] = new MyThread(i * loop, loop);
        }

        for (int i = 0; i < threadsCount; i++) {
            threads[i].start();
        }

        latch.await();

        long write_sum = 0;
        for (int i = 0; i < threadsCount; i++) {
            write_sum += threads[i].write_time;
        }

        long read_sum = 0;
        for (int i = 0; i < threadsCount; i++) {
            read_sum += threads[i].read_time;
        }
        long randow_read_sum = 0;
        for (int i = 0; i < threadsCount; i++) {
            randow_read_sum += threads[i].randow_read_time;
        }

        System.out.println();
        System.out.println("threads: " + threadsCount + ", loop: " + loop + ", rows: " + (threadsCount * loop));
        System.out.println("==========================================================");
        System.out.println("write_sum=" + write_sum + ", avg=" + (write_sum / threadsCount) + " ms");
        System.out.println("read_sum=" + read_sum + ", avg=" + (read_sum / threadsCount) + " ms");
        System.out.println("randow_read_sum=" + randow_read_sum + ", avg=" + (randow_read_sum / threadsCount) + " ms");
    }
}

$ cat /etc/issue
Debian GNU/Linux stretch/sid

$ psql --version
psql (PostgreSQL) 9.5.1
使用的 jdbc 包版本是 postgresql-9.4.1208.jre7.jar

$ mysql --version
mysql Ver 15.1 Distrib 10.0.23-MariaDB, for debian-linux-gnu (x86_64) using readline 5.2
使用的 jdbc 包版本是 mysql-connector-java-5.1.38.jar

$ java -version
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)

mariaDB 的结果
MyThread-3000 write end, time=101805 ms
MyThread-1000 write end, time=101949 ms
MyThread-0 write end, time=102006 ms
MyThread-3000 read end, time=191 ms
MyThread-2000 write end, time=102041 ms
MyThread-1000 read end, time=257 ms
MyThread-3000 randow read end, time=234 ms
MyThread-0 read end, time=271 ms
MyThread-2000 read end, time=272 ms
MyThread-1000 randow read end, time=161 ms
MyThread-0 randow read end, time=133 ms
MyThread-2000 randow read end, time=137 ms

threads: 4, loop: 1000, rows: 4000

write_sum=407801, avg=101950 ms
read_sum=991, avg=247 ms
randow_read_sum=665, avg=166 ms

pg 的结果
MyThread-3000 write end, time=27189 ms
MyThread-2000 write end, time=27210 ms
MyThread-0 write end, time=27225 ms
MyThread-1000 write end, time=27236 ms
MyThread-2000 read end, time=349 ms
MyThread-3000 read end, time=390 ms
MyThread-0 read end, time=417 ms
MyThread-1000 read end, time=431 ms
MyThread-2000 randow read end, time=301 ms
MyThread-3000 randow read end, time=309 ms
MyThread-0 randow read end, time=331 ms
MyThread-1000 randow read end, time=311 ms

threads: 4, loop: 1000, rows: 4000

write_sum=108860, avg=27215 ms
read_sum=1587, avg=396 ms
randow_read_sum=1252, avg=313 ms

mariaDB 真心慢!!!

@liuanxin
我昨天后来测了MariaDB10.1,修改一下data\my.ini,加入innodb_flush_log_at_trx_commit=2重新测就很快了。默认也是像MySQL一样,innodb_flush_log_at_trx_commit的值是1,每次insert一条新记录就会调fsync,所以会很慢。