Вставка Spring Data JPA BigList - PullRequest
       11

Вставка Spring Data JPA BigList

0 голосов
/ 24 апреля 2019

Я уже два дня пытаюсь сохранить список массивов с примерно шестью миллионами записей в моей базе данных Postgres с помощью Spring-Data-JPA. Все работает, но очень медленно. Мне нужно около 27 минут для всего. Я уже играл с размером партии, но это не принесло большого успеха. Я также заметил, что сохранение занимает все больше и больше, чем больше становится стол. Есть ли способ ускорить это? Я делал все это с SQLite раньше, там мне понадобилось всего около 15 секунд для того же количества.

Моя сущность

@Data
@Entity
@Table(name = "commodity_prices")
public class CommodityPrice {

    @Id
    @Column( name = "id" )
    @GeneratedValue( strategy = GenerationType.SEQUENCE )
    private long id;

    @Column(name = "station_id")
    private int station_id;

    @Column(name = "commodity_id")
    private int commodity_id;

    @Column(name = "supply")
    private long supply;

    @Column(name = "buy_price")
    private int buy_price;

    @Column(name = "sell_price")
    private int sell_price;

    @Column(name = "demand")
    private long demand;

    @Column(name = "collected_at")
    private long collected_at;


    public CommodityPrice( int station_id, int commodity_id, long supply, int buy_price, int sell_price, long demand,
            long collected_at ) {
        this.station_id = station_id;
        this.commodity_id = commodity_id;
        this.supply = supply;
        this.buy_price = buy_price;
        this.sell_price = sell_price;
        this.demand = demand;
        this.collected_at = collected_at;
    }
}

Моя вставка Класс

@Slf4j
@Component
public class CommodityPriceHandler {

    @Autowired
    CommodityPriceRepository commodityPriceRepository;

    @Autowired
    private EntityManager entityManager;

    public void inserIntoDB() {

        int lineCount = 0;
        List<CommodityPrice> commodityPrices = new ArrayList<>(  );
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();


        try {
            Reader reader = new FileReader( DOWNLOAD_SAVE_PATH + FILE_NAME_COMMODITY_PRICES );
            Iterable<CSVRecord> records = CSVFormat.EXCEL.withFirstRecordAsHeader().parse( reader );
            for( CSVRecord record : records ) {
                int station_id = Integer.parseInt( record.get( "station_id" ) );
                int commodity_id = Integer.parseInt( record.get( "commodity_id" ) );
                long supply = Long.parseLong( record.get( "supply" ) );
                int buy_price = Integer.parseInt( record.get( "buy_price" ) );
                int sell_price = Integer.parseInt( record.get( "sell_price" ) );
                long demand = Long.parseLong( record.get( "demand" ) );
                long collected_at = Long.parseLong( record.get( "collected_at" ) );

                CommodityPrice commodityPrice = new CommodityPrice(station_id, commodity_id, supply, buy_price, sell_price, demand, collected_at);
                commodityPrices.add( commodityPrice );

                if (commodityPrices.size() == 1000){
                    commodityPriceRepository.saveAll( commodityPrices );
                    commodityPriceRepository.flush();
                    entityManager.clear();
                    commodityPrices.clear();
                    System.out.println(lineCount);
                }

                lineCount ++;
            }
        }
        catch( IOException e ) {
            log.error( e.getLocalizedMessage() );
        }

        commodityPriceRepository.saveAll( commodityPrices );


        stopWatch.stop();

        log.info( "Successfully inserted " + lineCount + " lines in " + stopWatch.getTotalTimeSeconds() + " seconds." );
    }
}

Мои заявки. Свойства

# HIBERNATE
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
spring.jpa.hibernate.ddl-auto = update

spring.jpa.properties.hibernate.jdbc.batch_size=1000
spring.jpa.properties.hibernate.order_inserts=true

1 Ответ

0 голосов
/ 25 апреля 2019

Пока вы выполняете вставку в пакетном режиме, ваша стратегия генерации последовательности по-прежнему требует от вас одного оператора для каждой вставляемой записи. Таким образом, при размере пакета в 1000 записей вы выдаете 1001 оператор, что явно не соответствует ожидаемому.

Мои рекомендации:

  • включить протоколирование sql, чтобы увидеть, какие операторы отправляются в вашу базу данных. Я лично использую datasource-proxy , но использую все, что вам нравится.

  • изменить ваш генератор последовательности. Как минимум, используйте

@Id
@Column( name = "id" )
@GeneratedValue(generator = "com_pr_generator", strategy = GenerationType.SEQUENCE )
@SequenceGenerator(name="com_pr_generator", sequenceName = "book_seq", allocationSize=50)
private long id;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...