Рубрики
Без рубрики

Как включить многорядные вставки с помощью свойства конфигурации пакетных вставок перезаписи PostgreSQL

Узнайте, как свойство конфигурации JDBC с пакетными вставками перезаписи работает в PostgreSQL и как оно позволяет переписывать операторы ВСТАВКИ в многозначную ВСТАВКУ.

Автор оригинала: Vlad Mihalcea.

Владимир Ситников работал над многими оптимизациями драйвера JDBC PostgreSQL, и одним из них является свойство конфигурации reWriteBatchedInserts , о котором он недавно рассказал мне.

В этой статье вы увидите, как свойство конфигурации reWrite Batched Inserts JDBC работает в PostgreSQL и как оно позволяет переписывать инструкции INSERT в многозначную ВСТАВКУ.

Предполагая, что у нас есть следующая Должность сущность:

@Entity(name = "Post")
@Table(name = "post")
public class Post {

    @Id
    @GeneratedValue(
        strategy = GenerationType.SEQUENCE
    )
    private Long id;

    private String title;

    public Post() {}

    public Post(String title) {
        this.title = title;
    }

    //Getters and setters omitted for brevity
}

И, что мы включили пакетирование JDBC, установив следующее свойство конфигурации Hibernate:


Давайте сохраним 10 Сообщений сущностей:

for (int i = 0; i < 10; i++) {
    entityManager.persist(
        new Post(
            String.format("Post no. %d", i + 1)
        )
    );
}

Hibernate выполнит следующую инструкцию SQL INSERT:

Query: ["insert into post (title, id) values (?, ?)"], 
Params:[(Post no. 1, 1), (Post no. 2, 2), (Post no. 3, 3), 
        (Post no. 4, 4), (Post no. 5, 5), (Post no. 6, 6), 
        (Post no. 7, 7), (Post no. 8, 8), (Post no. 9, 9), 
        (Post no. 10, 10)
]

Это журнал уровня JDBC , созданный datasourceproxy , но чтобы быть действительно уверенным в том, что происходит за кулисами, нам также нужно активировать журнал PostgreSQL. Для этого нам нужно открыть файл postgresql.conf и задать свойству log_statements значение все :

log_statement = 'all'

Изучив журнал PostgreSQL, мы видим, что, несмотря на то, что была одна база данных туда и обратно, сервер базы данных должен обрабатывать каждый вызов выполнения индивидуально, и это может занять некоторое время:

LOG:  execute S_2: insert into post (title, id) values ($1, $2)
DETAIL:  parameters: $1 = 'Post no. 1', $2 = '1'
LOG:  execute S_2: insert into post (title, id) values ($1, $2)
DETAIL:  parameters: $1 = 'Post no. 2', $2 = '2'
LOG:  execute S_2: insert into post (title, id) values ($1, $2)
DETAIL:  parameters: $1 = 'Post no. 3', $2 = '3'
LOG:  execute S_2: insert into post (title, id) values ($1, $2)
DETAIL:  parameters: $1 = 'Post no. 4', $2 = '4'
LOG:  execute S_2: insert into post (title, id) values ($1, $2)
DETAIL:  parameters: $1 = 'Post no. 5', $2 = '5'
LOG:  execute S_2: insert into post (title, id) values ($1, $2)
DETAIL:  parameters: $1 = 'Post no. 6', $2 = '6'
LOG:  execute S_2: insert into post (title, id) values ($1, $2)
DETAIL:  parameters: $1 = 'Post no. 7', $2 = '7'
LOG:  execute S_2: insert into post (title, id) values ($1, $2)
DETAIL:  parameters: $1 = 'Post no. 8', $2 = '8'
LOG:  execute S_2: insert into post (title, id) values ($1, $2)
DETAIL:  parameters: $1 = 'Post no. 9', $2 = '9'
LOG:  execute S_2: insert into post (title, id) values ($1, $2)
DETAIL:  parameters: $1 = 'Post no. 10', $2 = '10'

Теперь давайте активируем Перезапишем пакетную вставку конфигурацию и повторим наш тестовый случай. Чтобы задать свойство Перезаписывать пакетные вставки , мы можем использовать PGSimpleDataSource следующим образом:

PGSimpleDataSource dataSource = 
    (PGSimpleDataSource) super.dataSource();
    
dataSource.setReWriteBatchedInserts(true);

Теперь, при повторном запуске нашего тестового случая, который вставляет 10 записей post , PostgreSQL регистрирует следующие записи:

LOG:  execute : insert into post (title, id) values ($1, $2),($3, $4),($5, $6),($7, $8),($9, $10),($11, $12),($13, $14),($15, $16)
DETAIL:  parameters: $1 = 'Post no. 1', $2 = '1', $3 = 'Post no. 2', $4 = '2', $5 = 'Post no. 3', $6 = '3', $7 = 'Post no. 4', $8 = '4', $9 = 'Post no. 5', $10 = '5', $11 = 'Post no. 6', $12 = '6', $13 = 'Post no. 7', $14 = '7', $15 = 'Post no. 8', $16 = '8'
LOG:  execute : insert into post (title, id) values ($1, $2),($3, $4)
DETAIL:  parameters: $1 = 'Post no. 9', $2 = '9', $3 = 'Post no. 10', $4 = '10'

На этот раз у нас есть только 2 выполнения вместо 10, которые могут ускорить пакетную обработку на стороне базы данных.

В этом ответе StackOverflow Владимир привел еще одну причину , по которой вам следует рассмотреть этот параметр. Если пакет довольно большой, драйвер PostgreSQL разделит его на более мелкие, чтобы решить проблемы взаимоблокировки TCP.

Свойство конфигурации reWriteBatchedInserts было добавлено в PostgreSQL JDBC версии 9.4.1209 (2016-07-15) , поэтому, если вы все еще используете ту же версию драйвера JDBC, настроенную при запуске проекта, вы можете рассмотреть возможность его обновления, если хотите ускорить пакетные вставки.

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