База размером 1 терабайт на Firebird. Технический отчет
Идея попробовать создать в Firebird базу размером 1 терабайт возникла после ознакомления с достижениями в этой области – на текущий момент наибольшая база данных (с осмысленной информацией) под Firebird – 450 гигабайт (указано в упрощенном варианте отчета).
- AMD Athlon 64 x2 5200. Работает на частоте 2782МГц вместо 2600МГц
- 4GB RAM
- Windows XP Professional SP3, 32bit
- MB MSI K9N Platinum
- NVIDIA GeForce 8800GT
- ОС и temp – ST3160815AS, 160GB, SATA II
- Вспомогательный – ST3200827AS, 200GB, SATA II
- Свежекупленный – ST31500341AS, 1.5TB, SATA II (Firmware CC1H)
Место для размещения будущей терабайтной базы есть, теперь надо решить, чем ее заполнить – для этого был выбран тест TPC-C, вернее, не сам тест, а загрузчик для теста. Таким образом, у нас будет OLTP-база в 1 терабайт.
Почему именно на десктопном компьютере, а не на сервере? Во-первых, так проще выполнить тест. Во-вторых, задача теста состоит в том, чтобы проверить возможность работы Firebird с такими большими базами, как таковыми. В третьих, сам факт о возможности работы с терабайтной базой данных на таком компьютере уже говорит о масштабируемости Firebird.
Результаты, полученные в тесте, вы можете примерить на ваше оборудование, которое может быть в 2, 3, 10, 20 раз мощнее (или окажется в 1.5, 2 или 3 раза хуже). Например, если вместо одного SATA-диска соорудить RAID 10 из 4-х таких же дисков, то весь тест скорее всего прошел бы раза в полтора быстрее.
Для теста был выбран Firebird 2.1.2.
План теста- Создать базу данных, без индексов, размером в 1 терабайт
- Создать индексы (штатные для TPC-C)
- Собрать статистику по БД
- Проверить работу запросов
- после подключения диска XP SP3 при загрузке упала в синий экран,
- диск инициализировать без проблем удалось на этой же машине в параллельно установленной Vista Business 64bit,
- в Vista попытка быстрого форматирования выдавала ошибку,
- в XP быстрое форматирование ошибку не выдавало, но и не форматировало.
Для заливки данных использовался Firebird SuperServer, т. к. загрузчик в основном производит только вставку, а в этом смысле производительность у SuperServer и Classic одинаковая. Первые 43 гигабайта были залиты за 2.5 часа, порциями по 100 warehouses (-W), после чего была собрана статистика (файл iba для IBAnalyst 2.x). Статистика собиралась 15 минут.
Далее заливка данных осуществлялась большими порциями.
При размере базы в 250 гигабайт была сделана остановка, и опять собрана статистика. Время сбора статистики – 1 час 48 минут (статистика в txt). Из этого было сделано предположение, что по финальной базе статистика будет собираться примерно 8 часов.
Далее заливка была продолжена. Во дневное время одновременно происходила работа в: Word, Excel, бухгалтерском ПО, PerfMon, TaskManager, DreamWeaver, FireFox, Chrome, TheBat… То есть, самая обычная офисная работа.
Скорость загрузки одного блока (100 warehouses) с течением времени приведена на графике. По вертикали – скорость заливки одного блока (чч:мм:сс), а по горизонтали – номер блока. Вы видите 3 плоских участка – это заливка ночью.
Всего чистого времени заливка заняла 70 часов (почти трое полных суток). С небольшими перерывами – 4 суток. Fbserver.exe в это время занимал примерно 80% процессорного времени одного ядра (или 40% двух), а загрузчик – от 5 до 40% одного ядра (посередине теста загрузчик было решено привязывать ко второму ядру, чтобы он не мешал fbserver.exe и не терял производительность на переключении между ядрами).
В сумме в базу было залито 6.2 миллиарда записей размером от 13 до 600 (в среднем 146) байт. Средняя скорость вставки записей – 24.5 тысячи в секунду (общее число записей поделить на время заливки).
Разумеется, по ночам скорость заливки не была постоянной. Мы с некоторым опозданием (примерно на 420 гигабайтах) догадались включить FBDataGuard – вот картинка роста размера базы данных и интенсивности транзакций (желтым цветом – транзакций в минуту):
Замедление вставки данных, похоже, не связано с размером БД, а скорее связано с особенностями загрузчика. Например, видно еще на 460 гигабайтах падение частоты старта транзакций с 200 до 100, а потом опять возрастание до 200. Днем запускались мелкие блоки, у них падение было вообще до 40 транзакций в минуту, а на 770 гигабайт, ночью, опять рост до 200.
- частоту старта транзакций
- количество свободной памяти
- количество хэндлов и тредов fbserver.exe
В частности, по Free Memory видно, что оно не опускалось ниже 1гб, и практически не связано с интенсивностью старта транзакций.
Тем не менее – ура! У нас теперь есть база данных размером 1 терабайт (именно 1 терабайт, то есть 1 099 900 125 184 байт).
Создание индексов и select countПонятно, что при таком размере базы сразу скопом все индексы лучше не создавать, т.к. это может занять очень длительное время, да и неизвестно, сколько они займут места. А свободного места на 1.5 терабайтном диске осталось 372 гигабайта.
Поэтому индексы создаем поштучно. Но в любом случае при их создании создаются temp-файлы (для сортировки значений индексируемого столбца), а значит, понадобится место для TEMP. На текущем компьютере со свободным местом предполагаемого объема было не очень, поэтому решено докупить SATA диск 640 гигабайт (куплен HDT721064SLA360), заменить имеющийся 200гб с копированием данных и перераспределением разделов в Acronis True Image.
В результате на диске H образовалось свободное место 378 гигабайт, и туда через firebird.conf был назначен temp. Тест диска для TEMP в HD Tune:
Поначалу мы решили, что собирать статистику без индексов неинтересно. Поэтому оценивали объемы таблиц, с которых можно начать индексирование, по предыдущей статистике 250 гигабайт. Также перед созданием некоторых индексов выполнялся select count, для оценки предполагаемого времени (не меньше) создания индекса по этой таблице.
Прочерки в ячейках означают, что информация или не замерялась, или неизвестна, или отсутствует. Таблица Записей Размер, Гб Время select count(*) Время создания индекса Размер temp-файла, Гб Размер индекса в БД, Гб WAREHOUSE 12400 0.002 0s 0 0 0.0 ITEM 100000 0.012 0.7s – – 0.0 DISTRICT 124000 0.017 0.7s 6s – 0.0 NEW_ORDER 111 600 000 32 20m 00s 23m 00s 4.56 0.8 CUSTOMER 372 000 000 224 – 41m 00s – 2.6 customer_last 1h 52m 32s 12.4 2.3 fk_cust_ware 2h 10m 51s – 2.3 HISTORY 372 000 000 32 – – – – ORDERS 372 000 000 25 32m 00s 45m 41s 15.2 2.5 STOCK 1 240 000 000 404 – 3h 34m 44s 41.5 9.2 ORDER_LINE 3 720 051 796 359 – 12h 6m 18s 182.0 29.3 У первых трех таблиц размер индексов в гигабайтах указан как 0, потому что не выше 0.7 мегабайт. У CUSTOMER два индекса – первый по ПК integer, smallint и smallint, и второй по varchar(16).
По таблице ORDER_LINE в первый раз создать первичный ключ не удалось – не хватило 378 гигабайт в TEMP? Мало того что эта таблица содержит 3.7 миллиарда записей, так еще и первичный ключ у нее состоит из smallint, smallint, integer и smallint. Решили отложить создание этого индекса на некоторое время.
Пришло время запустить gstat (есть несколько часов не за компьютером). Итоговое время – 7 часов 32 минуты 45 секунд (финальный файл txt). В пересчете в мегабайт в секунду получается "сканирование БД" со скоростью в среднем 39 мегабайт в секунду, что очень даже неплохо (при усредненном максимальном Transfer rate для данного диска 100мб в секунду).
Однако, статистику по ORDER_LINE gstat выдал с переполнением – 574915500 записей. Мы тут же связались с Владиславом Хорсуном, и выяснили, что gstat считает количество записей в 8-байтном целом числе, а вот выводит в 4-байтовом знаковом. Значит, число записей будет 3 720 051 796 (если у отрицательного числа убрать знак).
Создан репорт http://tracker.firebirdsql.org/browse/CORE-2519 и исправлен IBAnalyst 2.6 – если он получает число записей из статистики как отрицательное, то меняет знак у числа и выводит его. Вообще в IBAnalyst 2.6 были не только эти правки, но и ряд других, касающихся переполнений при различных операциях с такими большими числами, а также обработке статистики таблиц без индексов.
Попытались создать индекс по ORDER_LINE второй раз. Опять ошибка. Сообразили, что проблема не в нехватке дисковой или физической памяти, а где-то внутри Firebird, т. к. выдаваемое сообщение
Обратились опять к Владиславу, и он пришел к выводу, что не хватает количества блоков для сортировки, а это задается константой в коде. Создали http://tracker.firebirdsql.org/browse/CORE-2525. Владислав сделал тестовый билд Firebird 2.1.3, в котором эта константа увеличена. И создание индекса успешно завершилось за 12 часов. При этом размер файла сортировки был 182 гигабайта, а в базе индекс занял 29.3 гигабайт.
- Firebird 2.1.2 с модификацией – 31 минута 35 секунд, 32 минуты 31 секунда
- Firebird 2.1.2 оригинальный – 23 минуты 00 секунд, 25 минут 46 секунд
Пересобрали статистику только по индексам, это заняло 14 минут, т. к. индексы находятся "плотно" в конце файла базы данных. После чего собранная статистика по индексам была "вклеена" в полученный ранее файл статистики.
Как уже говорилось выше, создание индекса состоит из двух фаз – вначале данные из БД переносятся блоками во временный файл с одновременной сортировкой, а затем уже отсортированные данные переносятся обратно в базу данных как индекс. Мы наблюдали за этими процессами в PerfMon, вот наиболее типичные графики (для индекса customer_pk, таблица с 372млн записей).
Перенос данных в TEMP:
Перенос данных из TEMP в индекс:
ЗапросыНичего удивительного. Простое объединение, напомню что в warehouse 12400 записей, а в customer – 372 миллиона.
Теперь чуть иначе, некоторое количество данных ближе к концу БД
будет между 20 и 23 минутами.
Кроме того, по большим сортировкам с индексами и без есть достаточно подробный материал. Впрочем, можете прислать интересующий вас запрос, попробуем выполнить.
РезюмеНесмотря на "десктопность" компьютера и размер базы данных, тест прошел удачно, и по всем параметрам производительность вполне нормальная. Для Firebird терабайтная база данных не хуже и не лучше 1, 10 или 250 гигабайтной. Разумеется, для нормальной работы с такими объемами требуется более мощная дисковая подсистема, процессор бы неплохо побыстрее, и как минимум 4-х ядерный, и, наконец, 64-разрядная операционная система и сам Firebird.