forum.bitel.ru
http://forum.bitel.ru/

Кэшируемые PreparedStatement
http://forum.bitel.ru/viewtopic.php?f=19&t=7875
Страница 1 из 1

Автор:  Cromeshnic [ 25 мар 2013, 10:41 ]
Заголовок сообщения:  Кэшируемые PreparedStatement

Пишу Dao для своей сущности, хочу кэшировать PreparedStatement-ы.
Смотрю по коду, как это правильно делается.
Например, ru.bitel.common.model.AbstractDao<B> :

Код:
  protected PreparedStatement getByIdPS = null;

  ...

  protected B getById(int id)
    throws BGException, SQLException
  {
    PreparedStatement ps = this.getByIdPS;
    if (ps == null)
    {
      ps = this.getByIdPS = this.con.prepareStatement("SELECT * FROM " + this.tableName + " WHERE id=?");
    }

    ps.setInt(1, id);

    ResultSet rs = ps.executeQuery();
    Object result;
    Object result;
    if (rs.next())
    {
      result = getFromRS(rs);
    }
    else
    {
      result = null;
    }
    rs.close();

    return result;
  }


А как быть с многопоточностью?
Разве не может возникнуть ситуация, когда между строчками
Код:
    ps.setInt(1, id);
    ResultSet rs = ps.executeQuery();

выполнится ps.setInt() из другого потока для того же ps ?
Может быть я что-то упускаю?
Например, веб-сервисы могут использовать один и тот же Dao в разных потоках.

Автор:  dimOn [ 25 мар 2013, 16:36 ]
Заголовок сообщения:  Re: Кэшируемые PreparedStatement

Не могут, они (dao) как правило создаются внутри каждого метода вебсервиса.

Автор:  Amir [ 25 мар 2013, 16:39 ]
Заголовок сообщения:  Re: Кэшируемые PreparedStatement

В Dao передается sql.Connection, который тоже не любит, когда его используют сразу в нескольких потоках, особенно при транзакциях, поэтому каждому потоку - свой Connection - свой Dao.

Автор:  dimOn [ 25 мар 2013, 16:47 ]
Заголовок сообщения:  Re: Кэшируемые PreparedStatement

Заранее отвечая на вопрос «зачем тогда кешировать» могу ответить «низачем», не нужно ничего кешировать.
Вообще почти нигде не нужно кешировать, кроме случаев большого обращения подряд по одному и тому же запросу. cachePrepStmts=true в коннекте стоит если, то оно само постарается кешировать. Но для такого запроса это абсурд, т.к. создание статемента почти ничего не стОит относительно самого выполнения и общения с сервером. Я никогда не кеширую в таком случае и считаю это абсурдом и преждевременной эяоптимизацией.

Автор:  stark [ 25 мар 2013, 17:14 ]
Заголовок сообщения:  Re: Кэшируемые PreparedStatement

dimOn писал(а):
Заранее отвечая на вопрос «зачем тогда кешировать» могу ответить «низачем», не нужно ничего кешировать.

Мы проводили тесты. При кэшировании есть большой прирост производительности

Автор:  dimOn [ 25 мар 2013, 17:16 ]
Заголовок сообщения:  Re: Кэшируемые PreparedStatement

Ну так случаи нужно конкретные учитывать. Производительность при SELECT FROM один объект, как выше в примере, сильно вырастает? Чего именно производительность может вырасти? И как замеряли? Создать в цикле 100500 статементов? Ок.

Автор:  Amir [ 25 мар 2013, 17:32 ]
Заголовок сообщения:  Re: Кэшируемые PreparedStatement

cachePrepStmts=true в DBCP кэширует все PS по ключу-строке.
При динамических запросах WHERE id IN (...), в каждом из 300 соединений пула набирается куча никому не нужных PS.
А когда влючены серверные PS, они через какое-то время достигают лимита открытых PS в mysql (а PS при кэшировании через DBCP для mysql являются открытыми).

Автор:  Amir [ 25 мар 2013, 17:38 ]
Заголовок сообщения:  Re: Кэшируемые PreparedStatement

Код:
Вообще почти нигде не нужно кешировать, кроме случаев большого обращения подряд по одному и тому же запросу.
Согласен. Кэширование PS необходимо далеко не везде.

Автор:  Cromeshnic [ 26 мар 2013, 08:07 ]
Заголовок сообщения:  Re: Кэшируемые PreparedStatement

Ок, спасибо за комментарии.

Amir писал(а):
В Dao передается sql.Connection, который тоже не любит, когда его используют сразу в нескольких потоках, особенно при транзакциях, поэтому каждому потоку - свой Connection - свой Dao.

dimOn писал(а):
Не могут, они (dao) как правило создаются внутри каждого метода вебсервиса.


Вот например ru.bitel.bgbilling.kernel.module.server.service.ServiceServiceImpl использует ServiceManager, который extends AbstractIdDao<Service>, причём создаёт его при инициализации сервиса.

Автор:  stark [ 26 мар 2013, 10:29 ]
Заголовок сообщения:  Re: Кэшируемые PreparedStatement

Cromeshnic писал(а):
Ок, спасибо за комментарии.

Amir писал(а):
В Dao передается sql.Connection, который тоже не любит, когда его используют сразу в нескольких потоках, особенно при транзакциях, поэтому каждому потоку - свой Connection - свой Dao.

dimOn писал(а):
Не могут, они (dao) как правило создаются внутри каждого метода вебсервиса.


Вот например ru.bitel.bgbilling.kernel.module.server.service.ServiceServiceImpl использует ServiceManager, который extends AbstractIdDao<Service>, причём создаёт его при инициализации сервиса.

Сервисы могут использоваться и в конвертерах (надо загрузить много-много договоров, услуг из файла/сторонней базы данных) , там создается один сервис и много много раз используется . так в данном случае это оправдано. Вообще любую нашу Dao-ку могут использовать, по идее, так .

Автор:  dimOn [ 26 мар 2013, 15:34 ]
Заголовок сообщения:  Re: Кэшируемые PreparedStatement

Нужно просто не допускать многопоточного использования и всё. Остальное — ок.

Страница 1 из 1 Часовой пояс: UTC + 5 часов [ Летнее время ]
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/