Pull to refresh

Сравнение скорости выполнения 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 — * — *
* Не смог дождаться выполнения кода

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

Надеюсь статья оказалась вам полезной/интересной, раз вы дочитали до конца!
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.