相关疑难解决方法(0)

如何使用JpaRepository进行批量(多行)插入?

当从服务层调用long 的saveAll方法时,Hibernate的跟踪日志记录显示每个实体发出的单个SQL语句.JpaRepositoryList<Entity>

我可以强制它进行批量插入(即多行)而无需手动操作EntityManger,事务等甚至原始SQL语句字符串?

对于多行插入,我的意思不仅仅是从:

start transaction
INSERT INTO table VALUES (1, 2)
end transaction
start transaction
INSERT INTO table VALUES (3, 4)
end transaction
start transaction
INSERT INTO table VALUES (5, 6)
end transaction
Run Code Online (Sandbox Code Playgroud)

至:

start transaction
INSERT INTO table VALUES (1, 2)
INSERT INTO table VALUES (3, 4)
INSERT INTO table VALUES (5, 6)
end transaction
Run Code Online (Sandbox Code Playgroud)

而是:

start transaction
INSERT INTO table VALUES (1, 2), (3, 4), (5, 6)
end transaction
Run Code Online (Sandbox Code Playgroud)

在PROD中,我使用的是CockroachDB,性能差异很大.

下面是一个重现问题的简单示例(H2为简单起见). …

hibernate spring-data-jpa kotlin spring-boot cockroachdb

31
推荐指数
3
解决办法
4万
查看次数

Hibernate批量大小混乱

该程序一个接一个地执行数万个连续插入.我以前从未使用过Hibernate.我的性能非常慢(如果我只是手动连接并执行SQL,我的速度要快10-12倍.根据许多hibernate教程,我的batch_size设置为50.

这是一个来自单个插入的日志 - 也许你可以帮我理解究竟发生了什么:

START INSERT
11:02:56.121 [main] DEBUG org.hibernate.impl.SessionImpl - opened session at timestamp: 13106053761                                                                                            
11:02:56.121 [main] DEBUG o.h.transaction.JDBCTransaction - begin                                                                                                                               
11:02:56.121 [main] DEBUG org.hibernate.jdbc.ConnectionManager - opening JDBC connection                                                                                                             
11:02:56.121 [main] TRACE o.h.c.DriverManagerConnectionProvider - total checked-out connections: 0                                                                                                    
11:02:56.121 [main] TRACE o.h.c.DriverManagerConnectionProvider - using pooled JDBC connection, pool size: 0                                                                                          
11:02:56.121 [main] DEBUG o.h.transaction.JDBCTransaction - current autocommit status: false                                                                                                    
11:02:56.121 [main] TRACE org.hibernate.jdbc.JDBCContext - after transaction begin                                                                                                             
11:02:56.121 [main] TRACE org.hibernate.impl.SessionImpl - setting flush mode to: MANUAL                                                                                                       
11:02:56.121 [main] …
Run Code Online (Sandbox Code Playgroud)

java hibernate jdbc

30
推荐指数
2
解决办法
5万
查看次数

如何在Spring中的共享EntityManager上手动启动事务?

我有一个LocalContainerEntityManagerFactoryBeanEntityManager实例.

要快速删除整个表的内容,我想运行以下代码:

@Service
public class DatabaseService {
    @Autowired
    private EntityManager em;

    @Transactional
    public void clear() {
        em.createNativeQuery("TRUNCATE TABLE MyTable").executeUpdate();
    }
}
Run Code Online (Sandbox Code Playgroud)

结果:

ERROR org.springframework.integration.handler.LoggingHandler: javax.persistence.TransactionRequiredException: Executing an update/delete query
    at org.hibernate.jpa.spi.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:71)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:708)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:644)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65)
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)
Run Code Online (Sandbox Code Playgroud)

如果我做了这个改变:

public …
Run Code Online (Sandbox Code Playgroud)

java spring entitymanager spring-data-jpa

26
推荐指数
3
解决办法
3万
查看次数

COPY如何工作?为什么它比INSERT快得多?

今天,我花了一天时间来改进我的Python脚本的性能,该脚本将数据推送到我的Postgres数据库中.我以前是这样插入记录的:

query = "INSERT INTO my_table (a,b,c ... ) VALUES (%s, %s, %s ...)";
for d in data:
    cursor.execute(query, d)
Run Code Online (Sandbox Code Playgroud)

然后我重新编写了我的脚本,以便创建一个内存文件,而不是用于Postgres的COPY命令,它允许我将数据从文件复制到我的表:

f = StringIO(my_tsv_string)
cursor.copy_expert("COPY my_table FROM STDIN WITH CSV DELIMITER AS E'\t' ENCODING 'utf-8' QUOTE E'\b' NULL ''", f)
Run Code Online (Sandbox Code Playgroud)

这种COPY方法速度惊人.

METHOD      | TIME (secs)   | # RECORDS
=======================================
COPY_FROM   | 92.998    | 48339
INSERT      | 1011.931  | 48377
Run Code Online (Sandbox Code Playgroud)

但我找不到任何关于为什么的信息?它与多线程的工作方式有何不同INSERT,使其更快?

也看到这个基准:

# original
0.008857011795043945: query_builder_insert
0.0029380321502685547: copy_from_insert

#  10 records …
Run Code Online (Sandbox Code Playgroud)

python postgresql sql-insert postgresql-copy

19
推荐指数
2
解决办法
5423
查看次数