Сравнение скорости выполнения SQL-запросов к разным БД

Эта публикация является односторонним сравнением популярных реляционных баз данных. А именно: по времени выполнения SQL-запросов в различных БД при прочих равных условиях (тип запроса и размер таблицы).

Заметка: если вас интересует только результат тестирования — прошу к разделу Результаты.

image

Введение


Возник вопрос о выборе базы данных для веб-проекта. В рассматриваемом списке присутствовали: H2, MySQL (раздельно реализации InnoDB и MyISAM), MariaDB, PostgreSQL, Oracle g11 r2. Пришла мысль измерить скорость выполнения Java-кода по выполнению запроса к различным базам данных.

Для измерения скорости выбор пал на библиотеку JMH. Подключается просто, через maven-dependency в pom.xml:

<dependencies>
  <dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-core</artifactId>
    <version>${jmh.version}</version>
  </dependency>
  <dependency>
    <groupId>org.openjdk.jmh</groupId>
    <artifactId>jmh-generator-annprocess</artifactId>
    <version>${jmh.version}</version>
    <scope>provided</scope>
  </dependency>
</dependencies>
...
<properties>
  <jmh.version>1.19</jmh.version>
</properties>

Написание Java-метода для тестирования весьма лаконично, аннотации говорят сами за себя:

@State(Scope.Thread)
public class H2 {
  @Benchmark
  @BenchmarkMode(Mode.AverageTime)
  @OutputTimeUnit(TimeUnit.MICROSECONDS)
  public ResultSet testMethod() throws SQLException, ClassNotFoundException {
    ResultSet resultSet = statement.executeQuery(someQuery);
    return resultSet;
  }
}

Для JMH важно чтобы метод имел возвращаемый тип данных.

Запуск тестового метода выполняется из public static void main:

public static void main(String[] args) throws RunnerException, ClassNotFoundException, SQLException {	
		Options opt = new OptionsBuilder()
                .include(H2.class.getSimpleName())
                .warmupIterations(10)
                .measurementIterations(10)
                .forks(1)
                .build();
        new Runner(opt).run();
}

Перед запуском необходимо собрать проект через командную строку:

mvn clean install

Результат сборку должен будет представлять что-то вроде этого:

image

В pom.xml необходимо добавить maven-dependency для БД:

<dependency>
  <groupId>com.h2database</groupId>
  <artifactId>h2</artifactId>
  <version>1.4.196</version>
</dependency>

До того как производить выборку, необходимо создать таблицу с заданным количеством строк. Для подобного рода подготовительных операций в JMH существует аннотация Setup:

@Setup
public void prepare() throws ClassNotFoundException, SQLException {
  Class.forName(driverName);
  connection = DriverManager.getConnection(connectionName, root, password);
  statement = connection.createStatement();
  statement.execute("CREATE TABLE ...");
  for (int i = 0; i < rowCount; i++) {
    statement.execute("INSERT INTO ...");
  }
}

Для разрыва соединения и удаления таблицы по завершении метода используется аннотация TearDown:

@TearDown
public void disconnect() throws SQLException {
  statement.execute("DROP TABLE ...");
  connection.close();
}


Результаты


Согласно скорости выполнения кода по запросу к БД в таблицах размером от 100 до 100 000 строк на моем компьютере, рассматриваемые БД расположены в следующем порядке (время запроса выражено в микросекундах):
1-2. Oracle 1-2. PostgreSQL 2. H2 3. MyISAM 4-5. MariaDB 4-5. InnoDB
100 строк 499, 774 435, 367 124, 041 387, 613 487, 720 545, 770
1000 строк 559, 887 714, 510 708, 488 1 441, 750 2 634, 031 2 611, 083
10 000 строк 8 842, 546 4 236, 861 9 433, 653 10 359, 910 26 056, 574 25 008, 635
100 000 строк 18 965, 460 36 947, 172 2 357 105, 910 99 816, 738 — * — *
* Не смог дождаться выполнения кода

Весь исходный код расположен здесь.
Буду благодарен любой конструктивной критике и советам, а также результатам тестирования на вашем железе.

Надеюсь статья оказалась вам полезной/интересной, раз вы дочитали до конца!
Метки:
SQL, Java, JMH
Похожие публикации