Що таке СУБД в оперативній пам'яті і як вона ефективно зберігає дані

Сальвадор Дали, Дезінтеграція сталості пам'яті. 1952-1954. Полотно, олія.

Всім привіт. Хтось з вас, можливо, вже знайомий з СУБД для даних в оперативній пам'яті, але на всяк випадок — посилання можна знайти їх загальний опис. Якщо коротко, такі СУБД зберігають дані в оперативній пам'яті. Що це означає? Щоразу, відправляючи запит на пошук або оновлення даних, ви звертаєтеся тільки до оперативної пам'яті в обхід жорсткого диска на ньому ніякі операції не провадяться. І це добре, тому що оперативна пам'ять працює набагато швидше будь-якого диска. Прикладом такої СУБД є Memcached.

Секундочку, скажете ви, а як же відновити дані після перезавантаження або поломки машини з такою СУБД? Якщо на машині встановлена СУБД для зберігання даних тільки в оперативній пам'яті, про них можна забути: при відключенні живлення дані безслідно зникнуть.

Чи можна об'єднати гідності зберігання даних в оперативній пам'яті з надійністю перевірених часом СУБД зразок MySQL або Postgres? Звичайно! Це вплине на продуктивність? Ви здивуєтеся, але немає!

Зустрічайте СУБД для даних в оперативній пам'яті, що забезпечують їх збереження: Redis, Aerospike, Tarantool.

Ви можете запитати, як же ці СУБД забезпечують збереження даних? Фокус в тому, що всі дані раніше зберігаються в оперативній пам'яті, але кожна операція додатково записується в розташований на диску журнал транзакцій. Подивіться на зображення нижче:



Перше, що ви, можливо, винесете із цієї схеми, — швидкість виконання запитів анітрохи не страждає, незважаючи на те що тепер СУБД постійно створює записи в журналі. Продуктивність при цьому не просідає, бо всі запити, як і раніше, звертаються безпосередньо до оперативної пам'яті. Відмінні новини! :-) А як йдуть справи з оновленням даних? Кожне оновлення (назвемо його транзакцією) не відбувається тільки в оперативній пам'яті, але і записується на диск. На повільний диск. Така чи це проблема? Давайте подивимося на наступне зображення:



Транзакції завжди записуються в кінець журналу. У чому плюс такого підходу? Диск працює досить швидко. Якщо говорити про класичний жорсткому диску (HDD), він може записувати дані в кінець файлу зі швидкістю до 100 Мб/с. Не вірите? Запустіть цей тест з командного рядка Unix/Linux/macOS:

cat /dev/zero >some_file

І подивіться, як швидко збільшується розмір
some_file
. Отже, жорсткий диск дуже спритний при послідовної запису, проте його швидкість різко падає при довільного запису: зазвичай він здатний виконати близько 100 таких операцій.

При побайтової запису, коли кожен байт записується в довільне місце на жорсткому диску, ви можете побачити, що реальна максимальна продуктивність диска становить 100 байтів/с. Ще раз, всього-навсього 100 байтів/с! Різниця в шість порядків між песимістичної (100 байтів/с) і оптимістичною (100 000 000 байт/с) оцінками швидкості доступу до диска настільки велика тому, що для пошуку по довільному сектору на диску потрібно фізичний рух головки диска, тоді як при послідовному доступі можна зчитувати дані по мірі обертання диска; голівка при цьому залишається нерухомою.

Якщо говорити про твердотільні накопичувачі (SSD), тут ситуація краща з-за відсутності рухомих частин. Однак співвідношення песимістичної (1-10 тисяч операцій в секунду) і оптимістичною (200-300 Мбайт/с) оцінок залишається практично незмінним: чотири-п'ять порядків. Детальніше з цими показниками можна ознайомитись посилання.

Таким чином, наша СУБД для даних в оперативній пам'яті, по суті, наводнює журнал транзакціями зі швидкістю до 100 Мб/с. чи це Достатньо швидко? Дуже швидко. Припустимо, розмір транзакції становить 100 байтів, тоді швидкість буде дорівнювати мільйону транзакцій в секунду! Це настільки хороший показник, що вам абсолютно точно не доведеться хвилюватися про продуктивності диска при використанні подібної СУБД. За посиланням нижче знаходиться детальний тест продуктивності однієї СУБД в оперативній пам'яті при обробці мільйона транзакцій в секунду, де проблемним елементом є не диск, а процесор: https://gist.github.com/danikin/a5ddc6fe0cedc6257853.

Підведемо підсумок всьому вищесказаному про дисках і СУБД в оперативній пам'яті:

  1. СУБД в оперативній пам'яті не звертаються до диска при обробці запитів, не змінюють дані.
  2. СУБД в оперативній пам'яті все-таки звертаються до диска при обробці запитів, які змінюють дані, але працюють з ним на максимальній швидкості.
Чому ж традиційні дискові СУБД не беруть на озброєння описані техніки? По-перше, на відміну від СУБД в оперативній пам'яті, у традиційних СУБД необхідно зчитувати дані з диска при кожному запиті (давайте ненадовго забудемо про кешування, це тема для окремої статті). Заздалегідь невідомо, який наступний запит, тому можна вважати, що кожен раз буде вимагатися довільний доступ до диска, а це, нагадаю, песимістичний сценарій.

По-друге, дискові СУБД повинні зберігати дані таким чином, щоб змінені дані можна було негайно вважати, на відміну від СУБД в оперативній пам'яті, які не зчитують з диска, за винятком випадків, коли запускається при старті відновлення. Саме тому для швидкого зчитування дисковим СУБД потрібні особливі структури даних, щоб уникнути повного сканування журналу транзакцій.

Одна з таких структур — B/B+-дерево, прискорює зчитування даних. Недоліком цього дерева є необхідність змінювати його при кожному змінює дані запиті, що може призвести до падіння продуктивності з-за довільного доступу до диска. Досить багато движків СУБД засноване на B/B+-деревах, з популярних можна назвати InnoDB від MySQL і движок Postgres.

Існує інша структура, яка краще справляється з записом даних, — LSM-дерево. Це відносно новий тип дерев, який не вирішує проблему довільного зчитування, але допомагає позбутися від частини проблем, пов'язаних з довільною записом. Прикладами движків, використовують такі дерева, можуть служити RocksDB, LevelDB або Vinyl. На зображенні нижче наведена зведена інформація про типи СУБД і використовуються ними деревах:



Резюмуємо сказане: СУБД в оперативній пам'яті, що забезпечують збереження даних, як при читанні, так і при запису можуть працювати дуже швидко, а точніше — так само швидко, як і СУБД в оперативній пам'яті, які не зберігають дані на диску: перші використовують диск настільки ефективно, що він ніколи не стає проблемним місцем.

P. S.

Остання — по порядку, але не по значимості — тема, яку я хотів би торкнутися в статті, присвячена знімків стану. Зняття таких знімків необхідно для компактификации журналів транзакцій. Знімок стану бази даних — це копія всіх наявних даних. Знімка і журналів з останніми транзакціями достатньо для відновлення стану вашої бази даних. Тому, маючи свіжий знімок стану, можна видалити всі старі журнали транзакцій, що передують даті знімка.

Навіщо компактифицировать журнали? Тому що чим більше журналів, тим довше буде відновлення бази даних. І потім, адже вам не хочеться захаращувати диск застарілої та непотрібної інформацією (ну добре, старі журнали іноді здорово виручають, але давайте поговоримо про це в окремій статті).

По суті, періодично роблячи знімки стану, ви повністю скопіювати базу даних з оперативної пам'яті на диск. Як тільки копіювання закінчилося, можна сміливо видаляти всі журнали, в яких немає транзакцій, записаних пізніше останньої транзакції у вашому знімку стану. Досить просто, чи не так? А все тому, що всі транзакції починаючи з самого першого дня потрапляють в знімок.

Ви могли задатися питанням: як зберегти консистентное стан бази даних на диск і як визначити останню зафіксовану в знімку транзакцію за умови постійного надходження нових транзакцій? Про це ми поговоримо в наступній статті.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.