Проблемы с производительностью при использовании базы данных Squeryl и H2 для настольных приложений - PullRequest
1 голос
/ 15 января 2012

У меня есть настольное приложение, которое сохраняет свои данные в локальной базе данных H2.Я использую Squeryl для взаимодействия с базой данных.

Размер базы данных очень мал (около 10 КБ).Я испытываю серьезные проблемы с производительностью, и происходит обширный дисковый ввод-вывод.Я только читаю БД и поэтому ожидал, что полные данные могут быть кэшированы;Я даже установил размер кеша на некоторое значение (намного больше, чем общий размер БД).Также я попытался отключить блокировку безрезультатно.

Моя программа выполняет очень много небольших запросов к базе данных;в основном у меня есть Swing TableModel, который делает запрос для каждой записи таблицы (каждый столбец каждой строки).Я заключаю каждый из этих вызовов в блок Squeryl transaction.

Я создал профиль с использованием JVisualVM, и я подозреваю, что следующее дерево вызовов показывает проблему.Самый верхний метод - доступ для чтения из моего кода.

ссылка на снимок экрана JVisualVM.

Вопрос

Как это исправить или что яЯ делаю не так?Каким-то образом я ожидаю, что мне удастся сделать много небольших вызовов для БД, которая достаточно мала, чтобы ее можно было хранить в пределах 1 МБ памяти.Почему происходит этот дисковый ввод-вывод и как его избежать?

Ответы [ 2 ]

3 голосов
/ 15 января 2012

Глядя на скриншот, кажется, что вы выбираете из БД внутри метода getValueAt() вашей TableModel (имя метода getRowAt() в верхней части стека вызовов вызывает мое предположение).

Если мое предположение верно, то это ваша главная проблема. getValueAt() вызывается методом paint () JTable постоянно (возможно, несколько раз в секунду), так что это должно быть как можно быстрее.

Вы должны получить данные для JTable в одном запросе SQL, а затем сохранить результат в некоторой структуре данных (например, ArrayList или что-то в этом роде).

Я не знаю Squeryl, но я сомневаюсь, что вам действительно нужно заключать каждый SELECT в транзакцию. Из трассировки стека видно, что это вызывает массовую запись в H2. Вы пытались запустить SELECT без явного открытия (и закрытия) транзакции каждый раз?

1 голос
/ 17 января 2012

В конце концов, решение было очень простым. Я процитирую FAQ.

Задержка закрытия базы данных

Обычно база данных закрывается, когда закрывается последнее соединение с ней. В некоторых ситуациях это замедляет работу приложения, например, когда невозможно сохранить хотя бы одно соединение открытым. Автоматическое закрытие базы данных может быть отложено или отключено с помощью оператора SQL SET DB_CLOSE_DELAY <seconds>. Параметр <seconds> указывает количество секунд, в течение которых база данных будет оставаться открытой после последнего подключения к ней. Следующий оператор будет держать базу данных открытой в течение 10 секунд после закрытия последнего соединения:

SET DB_CLOSE_DELAY 10

Значение -1 означает, что база данных не закрывается автоматически. Значение 0 является значением по умолчанию и означает, что база данных закрывается при закрытии последнего соединения. Этот параметр является постоянным и может быть установлен только администратором. Можно установить значение в URL базы данных: jdbc:h2:~/test;DB_CLOSE_DELAY=10.

...