Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > MySql и Hibernate, как такое объяснить?


Автор: unkis 2.5.2007, 11:40
Ребята, задача заключается в следующем:

Надо в БД сохранить 800000 объектов.

Интересное начинается после 200000 объектов, жёсткий диск крутится без перерыву, нагрузка на процессор нулевая. до этого(до 200000) нагрузка на процессор была 100%.

После некоторого времени, жёсткий диск останавливается(почти останавливается),  и нагрузка на процессор опять 100% и потом опять падает и так продолжается и продолжается.

Производительность падает в разы. вопрос что же это за хрень такая? Может кто-то с подобным сталкивался?

Автор: tux 2.5.2007, 13:26
Сохранение выполняется одной транзакцией или операция на несколько разбита?

Автор: unkis 2.5.2007, 19:19
одной

Автор: tux 2.5.2007, 19:51
Цитата(unkis @  2.5.2007,  19:19 Найти цитируемый пост)
одной 

Когда ты выполняешь операции изменения записей, СУБД накапливает эти изменения в памяти (ей ведь надо либо зафиксировать все сразу либо откатить). Отсюда и своп. Разбей операцию на несколько транзакций.

Автор: unkis 3.5.2007, 12:44
Спасибо но проблема ещё вот в чём

у меня перед каждой вставкой идйт обращение к базе с выборкой,

вот так выглядит код



Код

for (RequestLocation location1 : requestLocationList) {
                    Location location =entityManager.find(Location.class,location1.getLocation().getLocation_id());
                    if (location == null) {
                    entityManager.persist(location1.getLocation());
                    entityManager.persist(location1);
                    }else{
                        location1.setLocation(location);
                        entityManager.persist(location1);
                    }
                }



то есть перед каждой вставкой, он проверяет существует ли такая запись или нет.



Код

Location location =entityManager.find(Location.class,location1.getLocation().getLocation_id());



и я так понимаю что база просто не знает что делать сохранять или выбирать, и поэтому происходит такой конфликт.

Что посоветуете по этому поводу?

Автор: tux 4.5.2007, 09:15
Цитата(unkis @  3.5.2007,  12:44 Найти цитируемый пост)
и я так понимаю что база просто не знает что делать сохранять или выбирать, и поэтому происходит такой конфликт.

Это, извиняюсь, как? Ты попросил MySQL вернуть запись с нужным первичным ключом, а она не поняла и решила что-то там сохранить? Это что за искусственный интеллект? Чего это MySQL тебя не слушается? Выбрось такую СУБД.

Цитата(unkis @  3.5.2007,  12:44 Найти цитируемый пост)
Что посоветуете по этому поводу?

Каждый из 800000 объектов ты пытаешься получить из базы. Видимо таких объектов в базе довольно много. Каждый из них хранится в кэше сессии. Вот тебе еще одна причина расходования памяти. Возможны следующие пути решения:
  • разбиение одной транзакции на несколько. Я уже предлагал, видимо тебя по каким-то причинам не устраивает
  • проверять существует ли объект в базе используя select count(*) from ..., если существует, тогда создавать объект и сохранять, если нет, то выполнять update ...
И прочитай внимательнее в документации к Hibernate раздел "Batch processing".

Автор: unkis 4.5.2007, 10:22
Цитата(tux @  4.5.2007,  07:15 Найти цитируемый пост)
Это, извиняюсь, как? Ты попросил MySQL вернуть запись с нужным первичным ключом, а она не поняла и решила что-то там сохранить? Это что за искусственный интеллект? Чего это MySQL тебя не слушается? Выбрось такую СУБД.


Да нет она слушается, просто для неё наверно выборка длится слишком долго, так как если отключить проверку и ещё кое где поменять то процесс идёт очень быстро, но мне нужна такая проверка.



Цитата(tux @  4.5.2007,  07:15 Найти цитируемый пост)
Каждый из 800000 объектов ты пытаешься получить из базы. Видимо таких объектов в базе довольно много. Каждый из них хранится в кэше сессии. Вот тебе еще одна причина расходования памяти.


в этом была проблема, я отключил кэш, и каждые 5000 делаю 
Код

entityManager.flush();
entityManager..clear();



Цитата(tux @  4.5.2007,  07:15 Найти цитируемый пост)
разбиение одной транзакции на несколько. Я уже предлагал, видимо тебя по каким-то причинам не устраивает


пробывал, писал каждые 5000
Код

bx2.comit();
bx2.begin();

эффекта никакого, тоже после 20000 тысяч начинется, жёсткий диск крутится без перерыву, нагрузка на процессор нулевая.



Цитата(tux @  4.5.2007,  07:15 Найти цитируемый пост)
проверять существует ли объект в базе используя select count(*) from ..., если существует, тогда создавать объект и сохранять, если нет, то выполнять update ...


1) а как я могу при помощи count(*) проверить существует ли объект, если он только считает.
2) и второе даже если он существует, то мне его надо вытащить и присвоить промежуточной таблицы и сохранить.
3) и почему entityManager.find(Location.class,location1.getLocation().getLocation_id()); не подходит?


Цитата(tux @  4.5.2007,  07:15 Найти цитируемый пост)
И прочитай внимательнее в документации к Hibernate раздел "Batch processing". 


да уже в роди в зад и вперёд прочитал, неужели что-то пропустил, если сохранять просто обекты без выборки, то проблем нет(проверял) он сохраняет и очень даже быстро, но вот когда делаешь проверку то и происходит выше описанная проблема. 

Автор: tux 4.5.2007, 11:21
Цитата(unkis @  4.5.2007,  10:22 Найти цитируемый пост)
а как я могу при помощи count(*) проверить существует ли объект, если он только считает.

Если до одного посчитает, значит существует. Хайтек такой.

Цитата(unkis @  4.5.2007,  10:22 Найти цитируемый пост)
и второе даже если он существует, то мне его надо вытащить и присвоить промежуточной таблицы и сохранить.

Как я вижу из кода, тебе нужно только одно поле изменить, зачем тебе весь объект?

Цитата(unkis @  4.5.2007,  10:22 Найти цитируемый пост)
и почему entityManager.find(Location.class,location1.getLocation().getLocation_id()); не подходит?

Потому и не подходит, что грузит весь объект в память. Зачем это нужно если можно только обновить поле, не тратя память совсем.

Автор: unkis 4.5.2007, 12:31
Цитата(tux @  4.5.2007,  09:21 Найти цитируемый пост)

Потому и не подходит, что грузит весь объект в память. Зачем это нужно если можно только обновить поле, не тратя память совсем. 

да только мне не нужно, не обновлять поле, а нужно вставить новый объект, ссылающийся не на новый объект, а на уже имеющийся в БД

Автор: AntonSaburov 4.5.2007, 14:39
Цитата(unkis @  4.5.2007,  12:31 Найти цитируемый пост)
да только мне не нужно, не обновлять поле, а нужно вставить новый объект, ссылающийся не на новый объект, а на уже имеющийся в Б

Если у тебя связь между объектами lazy, то тогда можно давать в качестве аргумента не полный объект location, а пустой, у которого установлен тольео первичный ключ - можно создать конструктор для Location с одним аргументом.

И тогда установка location можно прописать вот так

location1.setLocation(new Location(location1.getLocation().getLocation_id());

Это конечно просто набросок - посмотри сам внимательнее.

Автор: unkis 4.5.2007, 15:08
Сейчас не могу попробывать, попробую вечером.

А вы бы не могли мне объяснить за что отвечает атрибут lazy?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)