insert dla Hiberneta strasznie wolny

0

Czesc, mam do Was pytanie odnosnie predkosci. Chce wstawic liste beanow do bazy:

   getHibernateTemplate().saveOrUpdateAll(list);
 

moje pytania:

  1. Tabela jest zawsze pusta, wiec zbytecznym wydaje mi sie saveOrUpdateAll bo z tego co mi wiadomo to ta metoda wpierw bedzie sprawdzac czy dany rekord istnieje - wiec dla mnie to marnowanie cennego czasu.. nie znalazlam jednak metody typu saveAll, a przeciez nie bede robic petli po liscie i dla kazdego beana robic save.. Czy orientujecie sie moze czy jest cos typu saveAll?

  2. Zauwazylam ze saveOrUpdateAll jest wolny. Tzn: baza mysql, ilosc wstawionych rekordow to 2340, czas to 76sekund! To jakas masakra.. To jakbym sobie opakowala w jakiejs mojej klasie zwykle JDBC to dzialaloby mi to szybciej.. Macie moze pomysl jak moglabym to przyspieszyc? czy po prostu jest to wina tego ze Hibernate wpierw szuka czy dany rekord istnieje (czyli sprawe zalatwilaby podmianka metody saveOrUpdateAll na cos w stylu saveAll)?

dla porownania, jak zrobie liste w petli i na kazdym obiekcie dam save to czas wynosi 79sek.

pzdr,
misty

1

doprecyzuj czy bean jest prosty (jedna tabela) czy złożony (wiele tabeli), czy baza jest lokalnie czy po sieci... IMO wygląda to na bazę po sieci ze strasznie powolnym łączem. A i warto włączyć logowanie SQLek by zobaczyć co tam się w bebechach w rzeczywistości dzieje.

0
misty napisał(a):
  1. Tabela jest zawsze pusta, wiec zbytecznym wydaje mi sie saveOrUpdateAll bo z tego co mi wiadomo to ta metoda wpierw bedzie sprawdzac czy dany rekord istnieje - wiec dla mnie to marnowanie cennego czasu..

Nieprawda, Hibernate nie sprawdza, czy jest w bazie. On decyduje, czy ma zrobić insert, czy update na podstawie id (jeżeli id to Integer i jest równe null, to robi insert, jeżeli różne od null, to update).

http://docs.jboss.org/hibernate/orm/3.5/reference/en/html/batch.html

Najważniejsze, to ustawić "hibernate.jdbc.batch_size 20".

0

No nie do końca nie sprawdza. Jeżeli encja nie jest zarządzana przez hibernate i jest w bazie i nastąpi próba jej utrwalenia za pomocą metody persist to zostanie wyrzucony wyjątek. Jeżeli jednak będziemy chcieli utrwalić encję za pomocą metody merge to niezależnie od wartości ID jeżeli będzie null to zostanie wyrzucony wyjątek, jeżeli nie będzie null to najpierw zostanie wykonany select i dopiero w zależności od jego wyniku insert albo update.

0

@Krzysiek

 Nieprawda, Hibernate nie sprawdza, czy jest w bazie. On decyduje, czy ma zrobić insert, czy update na podstawie id (jeżeli id to Integer i jest równe null, to robi insert, jeżeli różne od null, to update).

troche bez sensu jest to co mowisz. Bo jesli id to Integer to twierdzisz ze zawsze robi update. A jesli takie id nie istnieje w bazie? Przeciez musi sprawdzic wpierw czy istnieje takie id..

jesli chodzi o **hibernate.jdbc.batch_size ** to pokombinowalam z roznymi wartosciami i najlepsze co mi sie udalo uzyskac to jakies 5sek do przodu, ale nadal taki wynik jest nie do zaakceptowania..

@koziolek

insert jest prosty, zadnych joinow, pod-selectow, nic z tych rzeczy. Entity typu:

@Entity
public class Test implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 3087339244605389787L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
   //tutaj 40 kolejnych pol glownie typu int, pare String i 2 Date
//gettery i settery

 

jesli chodzi o to czy baza zewnetrzna.. i tu mnie masz ;) gapa ze mnie. Aplikacje odpalam na serwerze zewnetrznym (loguje sie przez putty), bylam pewna ze bazka jest na tym samym serwerze (czyli dla niego bylby to localhost), ale teraz widze ze nie, baza jest jeszcze gdzie indziej. Jak sobie u siebie odpalilam, to czas mi spadl do 3ech sek.. jest roznica faktycznie. Ale to nie rozwiazuje problemu.. bo skoro doceolowo baza jest zewnetrzna, to ja to musze jakos przyspieszyc.. Macie jakies pomysly?

No i chcialabym dalej pociagnac temat istnienia metody typu saveAll, jestem pewna ze cos takiego przyspieszyloby mi dzialanie programu.. jakies sugestie?

 pzdr,
     misty
0

Hm... (tak to jest to sławetne Hm... zatem z szacunkiem).

Niewiele poradzisz na taką sytuację poza chyba opieprzeniem administratora, który ogranicza ruch pomiędzy serwerem bazy a serwerem z aplikacją. Na chwilę obecną sprawdziłbym jak wygląda rzeczywista przepustowość pomiędzy tymi serwerami. Pytanie masz dostęp do obu maszyn tak by dostać się do konsoli?

0

Nic nie musi sprawdzac. Hb uzywa JDBC i batching, a tam jest tak: mozesz wykonac update (jesli ma jakies id) i sprawdzic ile rekordow zostalo zmienionych. Jesli Hb dostanie 0 dla tego update, oznacza to ze nie bylo rekordu z takim id w bazie.
Ogolnie to najpierw select a pozniej update jest bardzo naiwna implementacja, ktora wcale nie musi byc uzywana.

0

@koziolek
tak, moge sie zalogowac przez putty na obie. Co proponujesz mi sprawdzic lub jakie testy wykonac?

@Mucka

dzieki za wyjasnienie. Czyli:

Jesli Hb dostanie 0 dla tego update, oznacza to ze nie bylo rekordu z takim id w bazie.

Czyli jesli dla update dostanie 0, to dopiero wtedy robi insert, tak?
Wiec w moim przypadku dla tych wszyskich rekordow wpierw bedzie probowal zrobic update, a potem insert. Tez uwazam ze slabe. Tzn dla przypadku dla ktorego stworzone jest saveOrUpdateAll pewnie nie, ale dla mojego (ja chce saveAll) to
nie jest fajne rozwiazanie, bo po co mi wpierw N-prob updateow?

Ogolnie to najpierw select a pozniej update jest bardzo naiwna implementacja, ktora wcale nie musi byc uzywana.

Czyli mam rozumiec ze update, a w przypadku kiedy update da 0 to insert bedzie szybsze niz wpierw select a pozniej insert?
Czy masz to poparte jakimis testami (lub wyczytales to w dokumentacji)? Nadal uwazam ze jest to stworzone dla typowe wykorzystania saveOrUpdateAll, a u mnie to sa nadal zbyteczne operacje..

wiec ponownie ponawiam pytanie o metode typu saveAll. Nie chce mi sie wierzyc ze jedyny moj wybor to petla i na kazdym save.. Ale szczerze, na prawde szukam po googlach i nie moge trafic na odpowiednika saveAll..

pzdr,
misty

0

Nie wiem co robi hibernate; ja tylko podalem przyklad ze to co mowi __krzysiek wcale nie jest bez sensu, ze select i pozniej update wcale nie sa jedyna droga. Co robi hb musisz sama sprawdzic / doczytac.

0

Najpierw włącz logowanie SQL > <property name="hibernate.show_sql" value="true" />
Następnie mając listę sqlek napsz prosty skrypt i uruchom go za pomocą konsolowego klienta mysql. Jeżeli czasy są podobne to:
http://blog.damontimm.com/how-to-test-connection-speed-between-two-machines/ w obu kierunkach.

0

wiesz co, ja z tym guzik zrobie, bo nie mam uprawnien by cokolwiek instalowac, a widze w tym linku ze cos tam trzeba.. ale ogolnie przesledze sobie te sqle. Wtedy zrozumiem jak jest dokladnie wykonywany ten saveOrUpdateAll. Moze sie dokopie czy mozna tym jakos manipulowac..

pzdr

0

Zrobilam maly test - napisalam klase ktora dziala mi czystym JDBC, przygotowalam sobie PreparedStatement, i co 100 moich beanow robilam executeBatch. Zmierzylam czas - ok jest szybciej (tak jak podejrzewalam, bo tutaj mam tylko INSERT, czyli to co mnie interesuje), ale nie wystarczajaco. Zyskalam jakies 12sek, czas nadal nie jest wiec zadowalajacy.. Wyglada na to ze to faktycznie problem z szybkoscia komunikacji pomiedzy tymi 2ma maszynami..

1 użytkowników online, w tym zalogowanych: 0, gości: 1