Re[8]: Hibernate vs JDBC. Производительность.
От: Igor.K США  
Дата: 07.06.07 19:08
Оценка:
U>да и в каком случаи использовать триггеры, а в каком хранимые процедуры?
Что бы не мучится, пишите все в хранимых процедурах и, когда надо, вызывайте их в триггерах.
"СССР — четыре слова и все лживые" — Вагрич Бахчанян
Re[3]: Hibernate vs JDBC. Производительность.
От: danila.master Россия  
Дата: 08.06.07 21:47
Оценка: 2 (1)
Здравствуйте, unkis, Вы писали:

U>Ребята я бюсь над этой проблемой уже почти ниделю, у меня ничего не выходит, Batch processing мне не подходит из-за скорости, да он позволяет вставлять 1000000 обеъектов при этом не получив ошибку о переполнении памяти, но делает он это гараздо медленнее чем через JDBC.

U>Я так понимаю что предназначение Batch processing, как раз устранение ошибки OutOfMemoryException, с чем он прикрасно справлдяется, но ни как для скоростной вставки.

U>Я никак не пойму, неужели нет возможности в Hibernate записывать в базу обекты, хотя бы приблезительно так же быстро, как это можно сделать через JDBC?


U>Что я делаю не так, ну подскожите пожалуйста, ткните пальцом.


Не поленился и проделал аналогичный тест. 20000 записей, СУБД — Oracle:

jdbc = 10.203 sec
hbn (without batching) = 41.344 sec
hbn (with batching = 10000) = 12.328 sec

Что могу посоветовать (у меня тоже не сразу быстро заработало):
— проверить, как hibernate генерит ключи (я поставил increment);
— выключить лог. Несмотря на batch-операцию, лог hibernate пишет для каждого объекта;
— проверить, что hibernate.jdbc.batch_size включен, а то в первом письме он был закоменчен

U> <!-- <property name="hibernate.connection.password" value="" />

U> <property name="hibernate.jdbc.batch_size" value="50" /> -->
Re[4]: Hibernate vs JDBC. Производительность.
От: n0name2  
Дата: 12.06.07 17:27
Оценка:
Здравствуйте, danila.master, Вы писали:

DM>Не поленился и проделал аналогичный тест. 20000 записей, СУБД — Oracle:


DM>jdbc = 10.203 sec

DM>hbn (without batching) = 41.344 sec
DM>hbn (with batching = 10000) = 12.328 sec


А JDBC у тебя тоже batches использует? Попробуй такой код, 20к записей Oracle должен вставлять за 1 — 2сек, а не за 10.

        Connection conn = DriverManager.getConnection("...");
        try {
            PreparedStatement pstmt = conn.prepareStatement("insert into t (?)");
            try {
                for (int i = 0; i < 20 * 1000;i++) {
                    pstmt.setInt(1, i);
                    pstmt.addBatch();
                }
                pstmt.executeBatch();
            } finally {
                pstmt.close();
            }
        } finally {
            conn.close();
        }
Re[5]: Hibernate vs JDBC. Производительность.
От: n0name2  
Дата: 12.06.07 17:29
Оценка:
Здравствуйте, n0name2, Вы писали:

сори, еще надо autocommit выключить:


        Connection conn = DriverManager.getConnection("...");
        try {
            conn.setAutoCommit(false);
            PreparedStatement pstmt = conn.prepareStatement("insert into t (?)");
            try {
                for (int i = 0; i < 20 * 1000;i++) {
                    pstmt.setInt(1, i);
                    pstmt.addBatch();
                }
                pstmt.executeBatch();
            } finally {
                pstmt.close();
            }
            conn.commit();
        } finally {
            conn.close();
        }
Re[4]: Hibernate vs JDBC. Производительность.
От: unkis  
Дата: 12.06.07 19:07
Оценка:
DM>Что могу посоветовать (у меня тоже не сразу быстро заработало):
DM>- проверить, как hibernate генерит ключи (я поставил increment);
DM>- выключить лог. Несмотря на batch-операцию, лог hibernate пишет для каждого объекта;
а как его выключить, можешь предсавить свой код, или на мыло выслать весь проект, что желательно unkis@gmx.de

спасибо
Re[6]: Hibernate vs JDBC. Производительность.
От: danila.master Россия  
Дата: 13.06.07 08:32
Оценка:
Здравствуйте, n0name2, Вы писали:

N>Здравствуйте, n0name2, Вы писали:


N>сори, еще надо autocommit выключить:


Oracle Oracle'у рознь. Я на удаленном сервере тестился.

Сейчас проверил локально — результат значительно ухудшился (чего и следовало ожидать). На 100 000 записей:
jdbc = 6.953
hbn = 12.234

Мой код:

        int mode = 2;
        if (mode == 1) {
            JdbcTemplate jdbc = new JdbcTemplate(ds);

            TransactionStatus status = transactionManager.getTransaction(null);
            int res = jdbc.queryForInt("select 1 from dual");
            System.out.println(res);
            long start = System.currentTimeMillis();
            jdbc.execute("insert into alarms (id, alarm_id, corr_id, cur_time) values(?, ?, ?, ?)", new PreparedStatementCallback() {
                public Object doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException {
                    for(int i = 0; i < 100000; i++) {
                        ps.setInt(1, i);
                        ps.setInt(2, 1);
                        ps.setInt(3, i);
                        ps.setDate(4, new java.sql.Date(System.currentTimeMillis()));
                        ps.addBatch();
                        if ((i % 1000) == 0) {
                            ps.executeBatch();
                        }
                    }
                    ps.executeBatch();
                    return null;
                }
            });
            transactionManager.commit(status);
            long end = System.currentTimeMillis();
            System.out.println("jdbc time " + (end - start) / 1000.0);
        } else if (mode == 2) {
            HibernateTemplate hbn = new HibernateTemplate(sessionFactory);
            
            TransactionStatus status = transactionManager.getTransaction(null);
            final AlarmsName an = (AlarmsName) hbn.get(AlarmsName.class, 1L);
            System.out.println(an);
            long start = System.currentTimeMillis();
            hbn.execute(new HibernateCallback() {
                public Object doInHibernate(Session session) throws HibernateException, SQLException {
                    for(int i = 0; i < 100000; i++) {
                        Alarms a = new Alarms();
                        a.setCorrId((long) i);
                        a.setAlarmsName(an);
                        a.setCurTime(new Date());
                        session.save(a);
                        if ((i % 1000) == 0) {
                            session.flush();
                            session.clear();
                        }
                    }
                    
                    session.flush();
                    return null;
                }
            });
            transactionManager.commit(status);
            long end = System.currentTimeMillis();
            System.out.println("hbn time " + (end - start) / 1000.0);
        }
Re[5]: Hibernate vs JDBC. Производительность.
От: danila.master Россия  
Дата: 13.06.07 08:37
Оценка:
Здравствуйте, unkis, Вы писали:

DM>>Что могу посоветовать (у меня тоже не сразу быстро заработало):

DM>>- проверить, как hibernate генерит ключи (я поставил increment);
DM>>- выключить лог. Несмотря на batch-операцию, лог hibernate пишет для каждого объекта;
U>а как его выключить, можешь предсавить свой код, или на мыло выслать весь проект, что желательно unkis@gmx.de

В моем случае для выключение лога понадобилось:
— в hibernate.cfg.xml свойство hibernate.show_sql установлено в false
— в конфигурации лога log4j.xml установлено
    <category name="org.hibernate.SQL">
        <priority value="INFO" />
    </category>


К сожалению, проект послать не могу, т.к. тестился в своем текущем рабочем проекте Код тестов запостил в предыдущем сообщении.
Re[7]: Hibernate vs JDBC. Производительность.
От: n0name2  
Дата: 13.06.07 09:30
Оценка:
Здравствуйте, danila.master, Вы писали:

DM>Oracle Oracle'у рознь. Я на удаленном сервере тестился.

DM>Сейчас проверил локально — результат значительно ухудшился (чего и следовало ожидать). На 100 000 записей:
DM>jdbc = 6.953
DM>hbn = 12.234

да, это уже больше похоже на правду. еще можно параллально в нескольких потоках попробовать вставку делать. ну, и разный тюнинг вроде игры с размером TCP пакета, разный размер batch, использованием массива вместо отдельных инсертов и т.д.

плюс, нужно, естественно, сначала пару раз прогнать код без замера времени, чтобы JVM разогрелся, ну, и -server -Xbatch тоже поможет.

но, в целом overhead гибернэйта в данном случае очень большой, а толку от него в данном тесте нет никакого, в т.ч. кода больше за счет XML дескрипторов. кстати, hibernate у тебя Oracle sequences использует?
Re[8]: Hibernate vs JDBC. Производительность.
От: danila.master Россия  
Дата: 13.06.07 10:17
Оценка:
Здравствуйте, n0name2, Вы писали:

N>Здравствуйте, danila.master, Вы писали:


DM>>Oracle Oracle'у рознь. Я на удаленном сервере тестился.

DM>>Сейчас проверил локально — результат значительно ухудшился (чего и следовало ожидать). На 100 000 записей:
DM>>jdbc = 6.953
DM>>hbn = 12.234

N>да, это уже больше похоже на правду. еще можно параллально в нескольких потоках попробовать вставку делать. ну, и разный тюнинг вроде игры с размером TCP пакета, разный размер batch, использованием массива вместо отдельных инсертов и т.д.


N>плюс, нужно, естественно, сначала пару раз прогнать код без замера времени, чтобы JVM разогрелся, ну, и -server -Xbatch тоже поможет.


Это да. Но меня тут порядок величины интересовал. У автора ветки разница получается более чем в 100 раз.

N>но, в целом overhead гибернэйта в данном случае очень большой, а толку от него в данном тесте нет никакого, в т.ч. кода больше за счет XML дескрипторов.


Для теста конечно толку нет А в определенном классе задач такое решение может быть вполне оправдано. Для большой и сложной схемы БД разработка и поддержка второго mapping'а для jdbc потребует больших усилий. Если производительность операций загрузки данных не является наиболее приоритетной/критичной или объем данных не сильно большой, можно и через hibernate грузить.

Кроме того, подозреваю, что основные затраты в hibernate связаны с использованием reflection. Так что если данные представлены в виде бинов, то выигрыш от jdbc может быть значительно меньше (для унифицированных решений). С другой стороны, hibernate можно привязать не к бинам, а к Map. Интересно, какой для этого случая получился бы результат.

N> кстати, hibernate у тебя Oracle sequences использует?


Обычно использую sequence, но для теста включил increment.
Re[9]: Hibernate vs JDBC. Производительность.
От: n0name2  
Дата: 13.06.07 10:27
Оценка:
Здравствуйте, danila.master, Вы писали:

DM>Это да. Но меня тут порядок величины интересовал. У автора ветки разница получается более чем в 100 раз.


в 100 раз, конечно, перебор...

DM>Для теста конечно толку нет А в определенном классе задач такое решение может быть вполне оправдано. Для большой и сложной схемы БД разработка и поддержка второго mapping'а для jdbc потребует больших усилий. Если производительность операций загрузки данных не является наиболее приоритетной/критичной или объем данных не сильно большой, можно и через hibernate грузить.


это все понятно. просто народ стал кидатся HBN юзать везде не задумываясь. причем, ИМХО, этот класс задач уже чем многие думают.

DM>Кроме того, подозреваю, что основные затраты в hibernate связаны с использованием reflection. Так что если данные представлены в виде бинов, то выигрыш от jdbc может быть значительно меньше (для унифицированных решений). С другой стороны, hibernate можно привязать не к бинам, а к Map. Интересно, какой для этого случая получился бы результат.


думаю, примерно также. Map add/put тоже не сахар.

DM>Обычно использую sequence, но для теста включил increment.


это некорректно. нужно sequences юзать, иначе вообще смысла нет никакого в инсертах. кстати, HBM "insert (...) values (...) returining ?" ситнаксис использует?
Re[10]: Hibernate vs JDBC. Производительность.
От: danila.master Россия  
Дата: 13.06.07 11:32
Оценка:
Здравствуйте, n0name2, Вы писали:

N>Здравствуйте, danila.master, Вы писали:


DM>>Обычно использую sequence, но для теста включил increment.


N>это некорректно. нужно sequences юзать, иначе вообще смысла нет никакого в инсертах.

А почему некорректно? Судя по описанию задачи тут явно пакетная загрузка данных. Маловероятно, что нужны ключи создаваемых объектов.

N>кстати, HBM "insert (...) values (...) returining ?" ситнаксис использует?


Судя по всему, нет. Есть sequence-identity (только для Oracle 10g), а можно самому написать.
Re[11]: Hibernate vs JDBC. Производительность.
От: n0name2  
Дата: 13.06.07 12:13
Оценка:
Здравствуйте, danila.master, Вы писали:

N>>это некорректно. нужно sequences юзать, иначе вообще смысла нет никакого в инсертах.

DM>А почему некорректно? Судя по описанию задачи тут явно пакетная загрузка данных. Маловероятно, что нужны ключи создаваемых объектов.

если у тебя кто-то еще данные параллельно пишет, то будет конфликт ключей.
Re[12]: Hibernate vs JDBC. Производительность.
От: danila.master Россия  
Дата: 13.06.07 12:38
Оценка:
Здравствуйте, n0name2, Вы писали:

N>Здравствуйте, danila.master, Вы писали:


N>>>это некорректно. нужно sequences юзать, иначе вообще смысла нет никакого в инсертах.

DM>>А почему некорректно? Судя по описанию задачи тут явно пакетная загрузка данных. Маловероятно, что нужны ключи создаваемых объектов.

N>если у тебя кто-то еще данные параллельно пишет, то будет конфликт ключей.


Это так. Мне почему-то казалось, что в обсуждаемой задаче эта ситуация отсутствует. Но это, конечно, только предположение (судя по названиям бинов — Request, RequestTime, TimeStamp — не правильное).
Re[13]: Hibernate vs JDBC. Производительность.
От: n0name2  
Дата: 13.06.07 13:51
Оценка:
Здравствуйте, danila.master, Вы писали:

DM>Это так. Мне почему-то казалось, что в обсуждаемой задаче эта ситуация отсутствует. Но это, конечно, только предположение (судя по названиям бинов — Request, RequestTime, TimeStamp — не правильное).


короче, корректный тест сложно сделать. но, для большого кол-ва легких запросов HBN тормозит, это точно.
Re[14]: Hibernate vs JDBC. Производительность.
От: unkis  
Дата: 13.06.07 16:53
Оценка:
DM>>Это так. Мне почему-то казалось, что в обсуждаемой задаче эта ситуация отсутствует. Но это, конечно, только предположение (судя по названиям бинов — Request, RequestTime, TimeStamp — не правильное).

Задача на самом деле выглядит так:

Есть как вы уже заметили следующие таблицы:

TimeStamp <------>RequestTime<--------> Request

так вот в RequestTime есть атрибут number, который отображает количество Request в определенное время(TimeStamp).
То есть перед тем как произвести вставку в БД, нужно произвести проверку: существует ли такой же Request в БД и Существует ли такой же TimeStamp в БД и если они существуют, то для них уже существует запись в промежуточной таблицы RequestTime, тогда получить эту запись, то есть объект RequestTime, и увеличить атрибут number на один, и после этого произвести апдейт объекта RequestTime.

Проверка, существует ли объект в БД или нет, это проверка почти всех атрибутов объекта в БД, на равенство всех атрибутов нового объекта.

так что вот такая вот задача.

для решение которой я применил следующий фокус.

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

Таким образом мы получаем проверку не по всем атрибутам, а только по ключу, то во много раз быстрее.

Но ту всё равно получается что пред каждой вставкой мне надо делать в худшем случаи три выборки, а в лучшем случаи только две.
Вот и задача как всё это ускорить.
Re[15]: Hibernate vs JDBC. Производительность.
От: n0name2  
Дата: 13.06.07 19:56
Оценка: 1 (1)
U>Вот и задача как всё это ускорить.

ты самое главное не написал — какая именно база у тебя. кстати, сверять ТОЛЬКО MD5 — неверно т.к. две строки могут иметь одинаковый hash и разные данные. нужно сверять и то и другое, сначала MD5 (а лучше SHA-1), конечно.

если бы у меня был Oracle то я бы сделал TimeStamp & RequestTime материализованными представлениями (Google — materialized views). тогда база будет сама подсчетом атрибута number заниматся. а в Request вставлял бы так

insert into request (...) select ?, ?, ? from dual where not exists (select 0 from request where md5 = ? and ...);
Re[16]: Hibernate vs JDBC. Производительность.
От: unkis  
Дата: 14.06.07 07:51
Оценка:
Здравствуйте, n0name2, Вы писали:

U>>Вот и задача как всё это ускорить.


N>ты самое главное не написал — какая именно база у тебя. кстати, сверять ТОЛЬКО MD5 — неверно т.к. две строки могут иметь одинаковый hash и разные данные. нужно сверять и то и другое, сначала MD5 (а лучше SHA-1), конечно.


База у меня MySQL, А можно немножко поп подробней про MD5, я что-то не понял почему они ьогут быть одинаковыми?
Re[17]: Hibernate vs JDBC. Производительность.
От: Blazkowicz Россия  
Дата: 14.06.07 07:59
Оценка: 1 (1) +1
Здравствуйте, unkis, Вы писали:

U>А можно немножко поп подробней про MD5, я что-то не понял почему они ьогут быть одинаковыми?

Тю, это же логика.
1) Множество всех строк больше чем множество всех их MD5 hash кодов. Это надо объяснять почему?
2) Каждой строке соответствует один MD5 hash код.
Вот и получается логичный вывод что есть такие строки которым соответствует одит и тот же MD5 hash код.
Re[18]: Hibernate vs JDBC. Производительность.
От: unkis  
Дата: 14.06.07 10:31
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Здравствуйте, unkis, Вы писали:


U>>А можно немножко поп подробней про MD5, я что-то не понял почему они ьогут быть одинаковыми?

B>Тю, это же логика.
B>1) Множество всех строк больше чем множество всех их MD5 hash кодов. Это надо объяснять почему?
извини за глупость, но всё же хотелось бы услышать


А как насчёт SHA алгоритма, там как дела обстоят с этим?
Re[19]: Hibernate vs JDBC. Производительность.
От: dshe  
Дата: 14.06.07 11:15
Оценка:
Здравствуйте, unkis, Вы писали:

U>Здравствуйте, Blazkowicz, Вы писали:


B>>Здравствуйте, unkis, Вы писали:


U>>>А можно немножко поп подробней про MD5, я что-то не понял почему они ьогут быть одинаковыми?

B>>Тю, это же логика.
B>>1) Множество всех строк больше чем множество всех их MD5 hash кодов. Это надо объяснять почему?
U>извини за глупость, но всё же хотелось бы услышать
сколько различных MD5 кодов может быть? 2^128 (длина digest'а 128 bit = 16 байт)
сколько различных строк может быть? если предположить, что символ это 1 байт, количество различных строк длиною 16 байт будет тоже 2^128. Но кроме строк длиною 16 байт существуют строки длиною 15 байт, 14 байт, 0 байт а также 17 байт, 18 байт... Получается, что мощность множества всех строк строго больше мощности множества всех MD5 кодов. Следовательно взаимно однозначного отображения между ними быть не может.

U>А как насчёт SHA алгоритма, там как дела обстоят с этим?

Точно так же. Как и с любым другим digest'ом.
--
Дмитро
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.