Проблема с производительностью на Java DB Derby Blobs & Delete - PullRequest
5 голосов
/ 21 мая 2009

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

Это в первую очередь с 10.4.2.0 под windows и solaris, хотя я также тестировал с новым кандидатом на выпуск 10.5.1.1 (так как в нем много изменений lob), но это не имеет существенного различия.

Проблема в том, что в случае таблицы, содержащей много больших BLOB-объектов, удаление одной строки может занять много времени (часто более минуты).

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

Схема таблицы проста, просто:

создание таблицы blobtest (целочисленное значение id, сгенерированное DEFAULT как идентификатор, b blob)

и я создал 7 строк со следующими размерами BLOB-объектов: 1024 байта, 1 МБ, 10 МБ, 25 МБ, 50 МБ, 75 МБ, 100 МБ.

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

Затем они были удалены с помощью оператора sql («удалить из blobtest, где id = X»).

Если я удаляю строки в том порядке, в котором я их создал, средние сроки удаления одной строки:

1024 байта: 19,5 секунд

1Mb: 16 секунд

10 МБ: 18 секунд

25 МБ: 15 секунд

50 МБ: 17 секунд

75Mb: 10 секунд

100 МБ: 1,5 секунды

Если я удаляю их в обратном порядке, средние сроки удаления одной строки:

100 МБ: 20 секунд

75 МБ: 10 секунд

50 МБ: 4 секунды

25Mb: 0,3 секунды

10 МБ: 0,25 секунды

1Mb: 0,02 секунды

1024 байта: 0,005 секунды

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

Таким образом, похоже, что время удаления связано с общим размером строк в таблице больше, чем размер удаляемого большого двоичного объекта.

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

Итак, есть ли у кого-нибудь объяснение производительности и какие-либо предложения о том, как обойти это или исправить? Это делает использование больших капель довольно проблематичным в производственной среде…

Ответы [ 4 ]

3 голосов
/ 22 мая 2009

Насколько я могу судить, Derby будет хранить только большие двоичные объекты, встроенные в другие данные базы данных, , поэтому вы получите BLOB, разделенный на тонну отдельных файлов страниц БД. Этот механизм хранения BLOB хорош для ACID и хорош для небольших BLOB (например, миниатюр изображений), но не подходит для более крупных объектов. Согласно документам Derby, отключение автоматической фиксации при работе с BLOB-объектами также может улучшить производительность , но это будет так далеко.

Я настоятельно рекомендую перейти на H2 или другую СУБД, если важна хорошая производительность на больших BLOB , и BLOB должны оставаться в БД. Вы можете использовать SQL-клиент SQuirrel и его плагин DBCopy для прямой миграции между СУБД (вам просто нужно указать его на драйвер JDBC Derby / JavaDB и драйвер H2). Я был бы рад помочь с этой частью, так как я сделал это сам, и не был счастливее.

В противном случае вы можете переместить большие двоичные объекты из базы данных в файловую систему. Чтобы сделать это, вы должны заменить столбец больших двоичных объектов в базе данных размером (если необходимо) большого двоичного объекта и местоположением ( URI или зависимая от платформы строка файла). При создании нового большого двоичного объекта вы создаете соответствующий файл в файловой системе. Расположение может основываться на заданном каталоге с добавлением первичного ключа. Например, ваша БД находится в «DBFolder / DBName», а ваши двоичные объекты находятся в «DBFolder / DBName / Blob» и имеют имя файла «BLOB_PRIMARYKEY.bin» или что-то подобное. Чтобы отредактировать или прочитать BLOB-объекты, вы запрашиваете у БД местоположение, а затем выполняете чтение / запись в файл напрямую. Затем вы записываете новый размер файла в БД, если он изменился.

3 голосов
/ 26 мая 2009

У меня точно такая же проблема, как и у вас.

Я обнаружил, что когда я делаю DELETE, derby фактически полностью «читает» файл большого сегмента. Я использую Filemon.exe, чтобы наблюдать, как он работает.

Мой размер файла 940 МБ, и для удаления только одной строки требуется 90 секунд.

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

Я предпочитаю пакетное удаление, чтобы обойти эту проблему. Я переписываю часть моей программы. Это было "где id =?" в авто-фиксации. Потом я много чего переписываю и теперь "где ID IN (?, .......?)" Заключено в транзакцию.

Общее время уменьшите до 1/1000, тогда как раньше.

Я полагаю, что вы можете добавить столбец для «пометить как удаленный» с расписанием, которое фактически выполняет пакетное удаление.

1 голос
/ 26 мая 2009

Я уверен, что это не тот ответ, который вам нужен, но для производственной среды с требованиями к пропускной способности я бы не использовал Java DB. MySQL также бесплатен и намного лучше справится с вашими требованиями. Я думаю, что вы на самом деле просто бьетесь головой об ограничении выбранного вами решения.

Обычно я использую Derby только в качестве тестового примера, и особенно только тогда, когда вся моя БД легко помещается в памяти. YMMV.

0 голосов
/ 21 мая 2009

Вы пытались увеличить размер страницы вашей базы данных ?

Информация об этом и многом другом содержится в руководстве Tuning Java DB , которое может оказаться полезным.

...