Я собираюсь добавить в пакет несколько миллионов сущностей. Пакетная вставка работает, но моя программа выполняет несколько операторов JDB C в фоновом режиме, чего я не хочу.
List < IceCream > iceList = new ArrayList < IceCream > ();
for (CSVRecord record: records) {
if (flushCounter > 40000) {
iceCreamRepository.saveAll(iceList);
iceList= new ArrayList < IceCream > ();
flushCounter = 0;
}
flushCounter++;
IceCream iceCream = new IceCream();
int id = getIdFromCSV();
iceCream.setId(id);
iceCream.set...
...
iceList.add(iceCream);
}
мой репозиторий:
public interface IceCreamRepository extends JpaRepository<IceCream, Long>
{
}
мой объект:
@Entity
@Table(name="IceCream")
public class IceCream
{
private static final long serialVersionUID = 1L;
@OneToMany(targetEntity=entity.OtherEntity.class, mappedBy="IceCream")
private Set<OtherEntity> otherEntitys = new HashSet<OtherEntity>();
@Id
private int id;
@Basic
@Column(name="import_tstamp")
@Temporal(TemporalType.TIMESTAMP)
private Date importTstamp;
@Basic
@Column(name="import_type", length=2147483647)
private String importType;
@Basic
@Column(length=2147483647)
private String text;
...
}
мой JPA Настройки:
spring.jpa.properties.hibernate.batch_versioned_data: true
spring.jpa.properties.hibernate.order_updates: true
spring.jpa.properties.hibernate.order_inserts: true
spring.jpa.properties.hibernate.generate_statistics: true
spring.jpa.properties.hibernate.jdbc.format_sql: true
spring.jpa.properties.hibernate.jdbc.batch_size: 1000
Пакетная вставка работает, но если я пытаюсь загрузить 100 сущностей, у меня есть 33 JDB C Заявления, которые проверяют идентификатор.
Это вывод для 33 сущностей:
2020-03-25 09:25:50.172 [scheduling-1] INFO net.ttddyy.dsproxy.listener.logging.SLF4JQueryLoggingListener - Name:, Connection:4, Time:1, Success:True, Type:Prepared, Batch:False, QuerySize:1, BatchSize:0, Query:["select ice0_.id as id1_4_0_, ice0_.text as text6_4_0_, ice0_.import_tstamp as import_10_4_0_, ice0_.import_type as import_11_4_0_, from iceCream ice0 where ice0_.id=?"], Params:[(1)]
2020-03-25 09:25:50.172 [scheduling-1] INFO net.ttddyy.dsproxy.listener.logging.SLF4JQueryLoggingListener - Name:, Connection:4, Time:1, Success:True, Type:Prepared, Batch:False, QuerySize:1, BatchSize:0, Query:["select ice0_.id as id1_4_0_, ice0_.text as text6_4_0_, ice0_.import_tstamp as import_10_4_0_, ice0_.import_type as import_11_4_0_, from iceCream ice0 where ice0_.id=?"], Params:[(2)]
2020-03-25 09:25:50.172 [scheduling-1] INFO net.ttddyy.dsproxy.listener.logging.SLF4JQueryLoggingListener - Name:, Connection:4, Time:1, Success:True, Type:Prepared, Batch:False, QuerySize:1, BatchSize:0, Query:["select ice0_.id as id1_4_0_, ice0_.text as text6_4_0_, ice0_.import_tstamp as import_10_4_0_, ice0_.import_type as import_11_4_0_, from iceCream ice0 where ice0_.id=?"], Params:[(3)]
2020-03-25 09:25:50.172 [scheduling-1] INFO net.ttddyy.dsproxy.listener.logging.SLF4JQueryLoggingListener - Name:, Connection:4, Time:1, Success:True, Type:Prepared, Batch:False, QuerySize:1, BatchSize:0, Query:["select ice0_.id as id1_4_0_, ice0_.text as text6_4_0_, ice0_.import_tstamp as import_10_4_0_, ice0_.import_type as import_11_4_0_, from iceCream ice0 where ice0_.id=?"], Params:[(4)]
2020-03-25 09:25:50.172 [scheduling-1] INFO net.ttddyy.dsproxy.listener.logging.SLF4JQueryLoggingListener - Name:, Connection:4, Time:1, Success:True, Type:Prepared, Batch:False, QuerySize:1, BatchSize:0, Query:["select ice0_.id as id1_4_0_, ice0_.text as text6_4_0_, ice0_.import_tstamp as import_10_4_0_, ice0_.import_type as import_11_4_0_, from iceCream ice0 where ice0_.id=?"], Params:[(5)]
... Моя программа пытается загрузить объекты, но не знаю, почему, я еще не вставил их. он делает это для 32 идентификаторов. Для каждого идентификатора, кроме первого (0) после этого вывода, есть пакетная вставка для всех 33 сущностей ...
2020-03-25 09:25:50.334 [scheduling-1] INFO net.ttddyy.dsproxy.listener.logging.SLF4JQueryLoggingListener - Name:, Connection:4, Time:11, Success:True, Type:Prepared, Batch:True, QuerySize:1, BatchSize:33, Query:["insert into iceCream(import_tstamp, import_type, text, id) values (?, ?, ?, ?)"], Params:[(2020-03-25 09:25:50.127,ice,teext,0),(2020-03-25 09:25:50.127,ice,teext,1),(2020-03-25 09:25:50.127,ice,teext,2)...]
.. после этого я получаю эту сводку:
2020-03-25 09:25:50.359 [scheduling-1] INFO org.hibernate.engine.internal.StatisticalLoggingSessionEventListener - Session Metrics {
2222222 nanoseconds spent acquiring 1 JDBC connections;
0 nanoseconds spent releasing 0 JDBC connections;
21234400 nanoseconds spent preparing 33 JDBC statements;
40600005 nanoseconds spent executing 32 JDBC statements;
27859771 nanoseconds spent executing 1 JDBC batches;
0 nanoseconds spent performing 0 L2C puts;
0 nanoseconds spent performing 0 L2C hits;
0 nanoseconds spent performing 0 L2C misses;
100978099 nanoseconds spent executing 1 flushes (flushing a total of 34 entities and 33 collections);
0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections)
}
если я использую только 1 сущность, то вывод:
2020-03-25 11:17:40.119 [scheduling-1] INFO org.hibernate.engine.internal.StatisticalLoggingSessionEventListener - Session Metrics {
1375995 nanoseconds spent acquiring 1 JDBC connections;
0 nanoseconds spent releasing 0 JDBC connections;
12024409 nanoseconds spent preparing 1 JDBC statements;
0 nanoseconds spent executing 0 JDBC statements;
5597005 nanoseconds spent executing 1 JDBC batches;
0 nanoseconds spent performing 0 L2C puts;
0 nanoseconds spent performing 0 L2C hits;
0 nanoseconds spent performing 0 L2C misses;
38446070 nanoseconds spent executing 1 flushes (flushing a total of 1 entities and 1 collections);
0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections)
}
для 2 сущностей показывает следующее (мой идентификатор начинается с 0, поэтому он только JDB C выполняет вторую сущность):
2020-03-25 09:25:50.172 [scheduling-1] INFO net.ttddyy.dsproxy.listener.logging.SLF4JQueryLoggingListener - Name:, Connection:4, Time:1, Success:True, Type:Prepared, Batch:False, QuerySize:1, BatchSize:0, Query:["select ice0_.id as id1_4_0_, ice0_.text as text6_4_0_, ice0_.import_tstamp as import_10_4_0_, ice0_.import_type as import_11_4_0_, from iceCream ice0 where ice0_.id=?"], Params:[(1)]
2020-03-25 11:25:00.180 [scheduling-1] INFO org.hibernate.engine.internal.StatisticalLoggingSessionEventListener - Session Metrics {
1446363 nanoseconds spent acquiring 1 JDBC connections;
0 nanoseconds spent releasing 0 JDBC connections;
13101435 nanoseconds spent preparing 2 JDBC statements;
11427142 nanoseconds spent executing 1 JDBC statements;
3762785 nanoseconds spent executing 1 JDBC batches;
0 nanoseconds spent performing 0 L2C puts;
0 nanoseconds spent performing 0 L2C hits;
0 nanoseconds spent performing 0 L2C misses;
22309803 nanoseconds spent executing 1 flushes (flushing a total of 2 entities and 2 collections);
0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections)
}
выход для 3:
2020-03-25 11:47:00.277 [scheduling-1] INFO org.hibernate.engine.internal.StatisticalLoggingSessionEventListener - Session Metrics {
1010843 nanoseconds spent acquiring 1 JDBC connections;
0 nanoseconds spent releasing 0 JDBC connections;
31706133 nanoseconds spent preparing 3 JDBC statements;
57180996 nanoseconds spent executing 2 JDBC statements;
3839505 nanoseconds spent executing 1 JDBC batches;
0 nanoseconds spent performing 0 L2C puts;
0 nanoseconds spent performing 0 L2C hits;
0 nanoseconds spent performing 0 L2C misses;
23923340 nanoseconds spent executing 1 flushes (flushing a total of 3 entities and 3 collections);
0 nanoseconds spent executing 0 partial-flushes (flushing a total of 0 entities and 0 collections)
}
... Итак, у меня два вопроса:
Почему у меня все это JDB C заявлений, когда я хочу только одну пакетную вставку? (и как мне это исправить)
Я пробовал это для нескольких миллионов объектов, но не могу увидеть какие-либо обновления в базе данных, пока программа не будет завершена. Я вызываю iceCreamRepository.saveAll (iceList); функционировать каждые 4000 строк. Я думал, что это запишет все сущности в базу данных. Мой оперативной памяти нет, у меня есть файл данных 10 ГБ и только 2 ГБ оперативной памяти. Если программа ожидает записи всех данных до конца, почему я не исчерпал RAM?