programing

대량 삽입 또는 최대 절전 모드로 업데이트하시겠습니까?

javajsp 2023. 9. 16. 08:41

대량 삽입 또는 최대 절전 모드로 업데이트하시겠습니까?

하루 CSV 파일에서 다소 많은 양의 데이터를 소비해야 합니다.CSV에는 약 12만 개의 레코드가 포함되어 있습니다.이것은 동면을 사용할 때 기어가는 속도로 느려집니다.기본적으로 최대 절전 모드는 saveOrUpdate()를 사용할 때 모든 INSERT(또는 UPDATE) 이전에 SELECT를 수행하는 것으로 보입니다. saveOrUpdate()로 지속되는 모든 인스턴스에 대해 실제 INSERT(또는 UPDATE) 이전에 SELECT가 실행됩니다.왜 이런 일을 하는지는 이해할 수 있지만 대량 처리를 하는 데는 매우 비효율적입니다. 그리고 대안을 찾고 있습니다.

네이티브 SQL(CSV를 동일한 방식으로 구문 분석하는)과 말 그대로 이 새 버전을 중심으로 순환하는 다른 버전을 사용했기 때문에 성능 문제는 이에 대해 최대 절전 모드를 사용하는 방식에 있다고 확신합니다.

그래서, 실제 질문에 대해, mysqls의 동면 대안은 "INSERT..."입니다.ON DUPLIC" 구문이 존재합니까?

또는 이를 위해 네이티브 SQL을 선택하면 최대 절전 모드 트랜잭션 내에서 네이티브 SQL을 수행할 수 있습니까?커밋/롤백을 지원할 수 있습니까?

대량 운영에는 많은 병목 현상이 발생할 수 있습니다.최상의 접근 방식은 데이터의 모습에 크게 좌우됩니다.일괄 처리에 대한 최대 절전 모드 매뉴얼 섹션을 살펴봅니다.

최소한 다음 패턴(매뉴얼에서 복사)을 사용하고 있는지 확인합니다.

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

for ( int i=0; i<100000; i++ ) {
Customer customer = new Customer(.....);
session.save(customer);
    if ( i % 20 == 0 ) { //20, same as the JDBC batch size
        //flush a batch of inserts and release memory:
        session.flush();
        session.clear();
    }
}

tx.commit();
session.close();

플랫 파일을 매우 복잡한 객체 그래프에 매핑하는 경우에는 보다 창의적인 작업을 수행해야 할 수도 있지만 기본적인 원칙은 각 플러시/커밋을 사용하여 좋은 크기의 데이터 덩어리를 데이터베이스로 푸시하는 것과 세션 레벨 캐시의 크기가 폭발하는 것을 방지하는 것 사이의 균형을 찾아야 한다는 것입니다.

마지막으로 데이터를 올바르게 삽입하기 위해 수집이나 계단식을 처리하기 위해 최대 절전 모드를 사용할 필요가 없는 경우 상태 비저장 세션을 사용하는 것을 고려합니다.

From Hibernate Batch Processing 업데이트를 위해 다음을 사용했습니다.

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

ScrollableResults employeeCursor = session.createQuery("FROM EMPLOYEE")
                                   .scroll();
int count = 0;

while ( employeeCursor.next() ) {
   Employee employee = (Employee) employeeCursor.get(0);
   employee.updateEmployee();
   seession.update(employee); 
   if ( ++count % 50 == 0 ) {
      session.flush();
      session.clear();
   }
}
tx.commit();
session.close();

하지만 삽입은 jcwayne 답변을 위해 갈 것입니다.

비슷한 질문에 대한 답에 따르면 데이터베이스의 업셋 기능을 사용하는 사용자 지정 저장 프로시저를 사용하여 최대 절전 모드를 설정하여 개체를 삽입할 수 있습니다.근데 안 예뻐요.

높은 처리량의 데이터 내보내기

처리나 변환을 하지 않고 데이터만 가져오려면 PostgreSQL과 같은 도구를 사용합니다.COPY데이터를 가져오는 가장 빠른 방법입니다.

일괄처리

그러나 기존 데이터와 수신 데이터 간의 변환, 데이터 집계, 상관/병합을 수행해야 하는 경우에는 애플리케이션 수준의 일괄 처리가 필요합니다.

이 경우 정기적으로 다음을 수행할 수 있습니다.

int entityCount = 50;
int batchSize = 25;
 
EntityManager entityManager = entityManagerFactory()
    .createEntityManager();
     
EntityTransaction entityTransaction = entityManager
    .getTransaction();
 
try {
    entityTransaction.begin();
 
    for (int i = 0; i < entityCount; i++) {
        if (i > 0 && i % batchSize == 0) {
            entityTransaction.commit();
            entityTransaction.begin();
 
            entityManager.clear();
        }
 
        Post post = new Post(
            String.format("Post %d", i + 1)
        );
         
        entityManager.persist(post);
    }
 
    entityTransaction.commit();
} catch (RuntimeException e) {
    if (entityTransaction.isActive()) {
        entityTransaction.rollback();
    }
    throw e;
} finally {
    entityManager.close();
}

또한 다음 구성 속성을 사용하여 JDBC 배치도 사용하도록 설정해야 합니다.

<property
    name="hibernate.jdbc.batch_size"
    value="25"
/>
 
<property
    name="hibernate.order_inserts"  
    value="true"
/>
 
<property
    name="hibernate.order_updates"  
    value="true"
/>

대량가공

Bulk processing 는 모든 행이 미리 정의된 필터링 기준과 일치할 때 적합하므로 단일 업데이트를 사용하여 모든 레코드를 변경할 수 있습니다.

그러나 수백만 개의 레코드를 수정하는 대량 업데이트를 사용하면 redo 로그의 크기가 늘어나거나 SQL Server와 같이 여전히 사용하는 데이터베이스 시스템에서 많은 잠금이 발생할 수 있습니다.

따라서 대량 업데이트가 많은 레코드를 변경할 수 있는 가장 효율적인 방법이지만, 장기간 실행되는 트랜잭션을 방지하려면 변경할 레코드 수에 주의를 기울여야 합니다.

또한 대량 업데이트와 최적 잠금을 결합하여 다른 OLTP 트랜잭션이 대량 처리 프로세스에 의해 수행된 업데이트를 손실하지 않도록 할 수 있습니다.

Sequence 또는 native generator를 사용하는 경우 Hibernate는 Select를 사용하여 ID를 가져옵니다.

<id name="id" column="ID">
    <generator class="native" />
</id>

hilo 또는 seqHiLo 생성기를 사용해야 합니다.

<id name="id" type="long" column="id">  
    <generator class="seqhilo">
        <param name="sequence">SEQ_NAME</param>
        <param name="max_lo">100</param>
    </generator>
</id>

"추가" 선택은 데이터에 대한 고유 식별자를 생성하는 것입니다.

HiLo 시퀀스 생성으로 전환하면 할당 크기만큼 데이터베이스에 대한 시퀀스 라운드 트립을 줄일 수 있습니다.HiLo 발생기에 대한 시퀀스 값을 조정하지 않으면 기본 키에 공백이 발생합니다.

언급URL : https://stackoverflow.com/questions/7349464/bulk-insert-or-update-with-hibernate