2012-01-05 17 views
12

Java programımdan çağrılması gereken bir oracle stored proc sahibim. Parametreleri saklanan proba iletmek için CallableStatement kullanmıştım. Ben oracle ince sürücü kullanıyorum (ilgili jndi girdisine karşı web mantık sunucusunda yapılandırılmış). Bu saklanan proc herhangi bir OUT değeri yok. Bu saklanan proc sayısal bir değeri kabul eder ve alınan değer temelinde db'de birçok güncelleme yapar.HazırlandıStatement, CallableStatement and Performance Considerations

Bir bağlantı nesnesi alıyorum ve sonra bu kaydedilmiş proc döngüsüne (20 sayıyı geçmek için 20 kez) arayın. Bu depolanmış probu doğrudan bir oracle istemcisinden çağırdığımda, yürütme 2-3 saniyede tamamlanır. Ancak davranış benim java kodumdan tahmin edilemez. Bazı çağrıların tamamlanması 30-40 saniye sürüyor.

CallableStatement yerine PreparedStatement kullanmayı denedim ve marjinal performans iyileştirmesini (davranış hala tutarsız olsa da) görebiliyordum.

  1. benim dava PreparedStatement yerine CallableStatement storedproc herhangi OUT parametreleri yok verilen kullanmak için sorun olur mu?
  2. PreparedStatement'un CallableStatement üzerinde bir performans artışıyla karşılaşmasının bir nedeni var mı, yoksa hatalı bir şekilde gözlemlediğim bir şey mi?
  3. Bu performans sorununu çözmek için daha iyi bir yaklaşım var mı?
+3

Kod gönderebilir misiniz? Alternatif olarak, her yinelemeyle bağlantınızın kurulmadığını doğrulayın (tek bir bağlantıyı tekrar tekrar kullanmak yerine) ve her bir yinelemeyle 'conn.prepareCall()' aramayacağınızı onaylayın (yalnızca '.setInt yerine döngü içinde) 've' .execute(). – Matt

+1

Saklı yordamınızı birden çok kez çağırıyorsunuz, değil mi? Toplu iş aramalarını denediniz mi? http://docs.oracle.com/javase/1.3/docs/guide/jdbc/getstart/callablestatement.html bkz. 7.1.3 –

+1

20 arama yapmak yerine, neden anonim olmayan bir PL/SQL bloğu denemiyorsunuz? çağrı proc ... çağrı proc ...... end;) saklanan procunuzu 20 kez çağırır ve veritabanına anonim bir blok ile bir çağrı yapar. – GriffeyDog

cevap

8

Yorumunuzdan, kendi döngüsünüzde prepareCall var. Hazırlanan ifadelerin (ve çağrılabilir ifadelerin) bir avantajı, bir kere hazırlayabilmeniz ve daha sonra parametrelerden geçirilen değerleri değiştirebilmenizdir; çağrının her hazırlandığı zaman havai bir yük vardır, bu yüzden döngünüzün dışına getirebilirseniz, çalışma süresinin azaldığını görebilirsiniz. AutoCommit'i kapatmanın, her bir taahhütte bir yük olduğu için, yardımcı olabileceğini de görebilirsiniz.

conn.setAutoCommit(false); 
CallableStatement stmt = conn.prepareCall(sql); 
while(true) { 
    stmt.setInt(1, value); 
    stmt.execute(); 
} 
conn.commit(); 
conn.setAutoCommit(true); 

( conn.setAutoCommit(true) işlemek yok, ama daha net içerikli olarak bulabilirsiniz).

+0

Teşekkürler Matt. Bunu çok daha iyi anlıyorum. Bunu ve Sergio'nın önerisini deneyeceğim.Zamanını ve yardımını takdir ediyorum :) –

+0

Merhaba Matt - hem sizin hem de Sergio'nın önerdiği yaklaşımları denedim, ancak java kodumla gerçekleştirildiğinde hala yavaştır. –

+0

Güncelleme: Prosedürün kendisi benim oracle istemcimi kullanarak doğrudan erişmeyi denediğimde, prosedürün kendisinin çok yavaş olduğunu tahmin ediyorum - her sayı için yaklaşık 2 dakika sürüyor.Bu, günün farklı zamanlarında farklı davranır ve araştırmam gereken bir şeydir. Yardımların için teşekkür ederim. –

1

Toplu iş kullanmayı düşünmüyor musunuz?

conn.setAutoCommit(false); 
CallableStatement stmt = conn.prepareCall(sql); 
while(true) { 
    stmt.setInt(1, value); 
    stmt.addBatch(); 
} 
stmt.executeBatch() 
conn.commit();