回答

收藏

带有HIBERNATE的JPA插入速度非常慢

技术问答 技术问答 299 人阅读 | 0 人回复 | 2023-09-14

我正在尝试通过使用JAP和HIBERNATE向SQL Server 20080 U0 e+ D* q( E; ?) X, S; n
R2插入一些数据。一切都“正常”,除了它非常慢。要插入20000行,大约需要45秒,而C#脚本大约需要不到1秒。
( X$ f  ]) Z2 s' O) k这个领域的任何资深人士都可以提供帮助吗?我会很感激。% }8 @3 `8 z$ W6 ~/ `
更新:从下面的答案中得到了一些很好的建议,但仍然无法按预期工作。速度是一样的。
( V" z2 G# b5 ]" {1 p这是更新的persistence.xml:
# K% L3 e; D0 d6 [* T9 g/ k! a) [/ s. G7 @6 l  g% W& S
    org.hibernate.ejb.HibernatePersistence
/ r: c/ s! e6 `% a    cluster.data.persist.sqlserver.EventResult. ~7 i+ G: ^5 F5 s# C
    true' Q' X9 U- G+ t
    2 v, m" ?  ]& T7 w# F4 V
        / S' l7 h- i7 [7 A' D
        ' Y0 O7 v- T( s! }
        
, V" T6 x. U8 b( r! P  y& C        
- x  h5 ^8 `- m1 ?" W        % A4 q/ A1 E' q: Q! ]
        & b9 g5 b1 `5 V  I$ J
        
- B1 `8 C. p! w0 n4 S$ A          B/ s  V, U  `% h5 U
        
  }3 f* i% B; W) e8 L" q8 s7 f- O$ F( v$ i/ o        
" Z, |% b9 ^) h6 ]          N/ g  h# R1 A) L9 U
        
4 }  p7 v/ _/ G( s        
; E% F! M* o* X! Q* {        
: D5 O3 K  p/ g9 z        . G. ?1 e* U" W) e; I
   
5 v9 K7 ?! H' X; H  _$ u; }: ~  s4 q7 r* \+ j1 }# K
这是更新的代码部分:
$ Z# U& l2 G' q7 X( X( V- jpublic static void writeToDB(String filePath) throws IOException {1 A5 e. E! f4 e# j
    EntityManager entityManager = entityManagerFactory.createEntityManager();
9 d' L, Y' X. b, P" o    Session session = (Session) entityManager.getDelegate();
( u3 a, i: z3 a  c. W  _    Transaction tx = session.beginTransaction();! U2 k) o) B4 _' a2 ^: F
    int i = 0;
' c; E0 P# D7 g$ p* n    URL filePathUrl = null;
- U0 {1 V( X' {. p+ X) j    try {
- A  C' w+ Z$ y$ Z        filePathUrl = new URL(filePath);( C2 \* C4 P5 s/ i* V2 q
    } catch (MalformedURLException e) {
+ Z) @" S+ i, t        filePathUrl = (new File(filePath)).toURI().toURL();5 y/ V- t' h0 F
    }9 ]$ H4 e$ U# ]9 z( F3 X/ t
    String line = null;
  ]+ h  C. j% m    BufferedReader stream = null;
3 N+ L% u! h; h/ ]8 g4 S6 M/ a' b1 g    try {8 ]! U/ w3 c. g# m/ V- j  i
        InputStream in = filePathUrl.openStream();
" ^$ u1 Q6 j% @! W! y9 d/ I' T        stream = new BufferedReader(new InputStreamReader(in));
3 Q& Z% z2 S6 R  C& V. i" g1 Z  m
        // Read each line in the file! h( E5 {# g# g
        MyRow myRow = new MyRow();
- b: w  s3 I) I! q9 U. `        while ((line = stream.readLine()) != null) {( C' Z4 b' ~- Q% e$ u/ E* y
            String[] splitted = line.split(",");
& e6 j3 x+ C/ l$ L' M# f3 B5 S            int num1 = Integer.valueOf(splitted[1]);
5 c8 }! r* s9 q8 y8 f$ B. }6 ]            float num2= Float.valueOf(splitted[6]).intValue();% Y% W" ~' O; F+ K& z9 h& g
            myRow.setNum1(num1);
5 ?) n" m' Y* d3 m# o" J& A' {" r            myRow.setNum2(num2);7 n9 i1 t% s# |" d( q
            session.save(myRow);% E% ~: V9 U' U3 S4 \" H
            if (i % 50 == 0) {
  n' \0 O' b& S$ w( I" r/ q                session.flush();' B- \: O" r8 A; {0 @
                session.clear();& m5 _9 H! j% d
            }; w" E/ J& _; R! T% a2 b
            i++;( `& Z" x2 a& m! S: _$ u: l
        }. P+ [) @0 a! G) |
        tx.commit();* Q. }, f6 M* p) m3 o. j0 l( V
    } finally {& z8 j! o+ D  t! U: D
        if (stream != null)
9 k& m. L6 q; f0 i9 Z: ]: J5 ]            stream.close();5 r) H/ [; A! x& g/ F  q
    }
/ Y; ?( ]" S1 U$ K0 q5 S4 Z' n    session.close();. ~( j) K7 h4 i: Q7 c2 D
}! g% T* |. Z3 a
已更新,这是MyRow的来源:
4 H' |, X. ~/ o  g# W  [@Entity
# T4 \/ I# @& k- O  ]@Table(name="MYTABLE"); x( l! M8 `% o2 I/ l6 H
public class MyRow {
1 c& {. h/ C7 ~2 S, S@Id; W( s5 [: }% ^  |
@GeneratedValue(strategy=GenerationType.IDENTITY) ' H3 A/ O# ?  I% [
private Long id;/ Y- C. n" ?8 E6 a- ^# b% d5 e
@Basic% F2 m! D8 ]4 g2 `9 N5 z
@Column(name = "Num1")
+ m9 C! u  v5 o" Q9 Y/ Vprivate int Num1;9 t5 ^5 A# J/ J3 o6 Z, Q" R
@Basic
, A& @- U5 w2 X1 z% M@Column(name = "Num2")* _( f* J6 F! S( o
private float Num2;! r; @1 j+ [! D4 i1 Z
public Long getId() {
9 ]7 o; M; l& ^3 U    return id;
" B2 h1 {5 v+ i" W# Z}
1 @  W. z; E& _0 G% vpublic void setId(Long id) {6 T, ~* H* _  g. G6 ?
    this.id = id;# O/ X* V  ^8 \' z$ y
}( k! z* y8 d" N/ ]( g
public float getNum1() {* \, E( g% M% `0 C* O! T  h  J) Z
    return Num1;; j- s, {( _9 o, ~* @% {
}5 C7 N1 |* U6 b+ B/ w& T, M- I
public void setNum1(float num1) {
7 n6 t; Y5 n  X! d* ]$ R    Num1 = num1;6 ?' m5 E, N; o: L. C" W
}2 m- E: s, D& G& u- l1 Q3 X4 \
public int getNum2() {% a9 i5 Y; {" ]! P! g
    return Num2;
! M7 P3 \) R8 j+ X! ?# L}
$ x0 j: L- N& `$ {. b3 `public void setNum2(int num2) {
, a* s7 Y; M& i. F0 Z2 Y/ t! Z0 \    Num2 = num2;
$ W3 X7 n4 K& f% E+ i. k8 ~}, i0 P4 J. x8 ^" ?3 F* j) _
}* C- R5 K! D+ a4 F+ \8 u2 H! j
               
" S" A" K8 h: x+ |% [解决方案:
( q. }5 S% N% k9 B& K                1 S# t$ V; |. L/ Z2 {

9 I0 f+ M; t9 H0 r  r& p& w
$ R! c4 B; U: E) c7 a: z                要启用JDBC批处理,您应该将hibernate.jdbc.batch_size属性初始化为10到50之间(仅int)- Y" T, T1 t+ y2 Q
hibernate.jdbc.batch_size=50
( q2 B/ ~# U% u. j  k% S如果它仍然不如预期的那么快,那么我将回顾上面的文档,同时注意“注意”和第4.1节。特别是提示:“如果使用身份标识符生成器,??则Hibernate会透明地禁用JDBC级别的插入批处理。”
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则