Як оптимізувати витрати на PostgreSQL у хмарі за допомогою багаторівневого зберігання

pic

Оскільки галузі, такі як Інтернет речей (IoT), фінанси та охорона здоров'я, генерують величезні обсяги даних, масштабовані та ефективні рішення для зберігання в хмарі стали необхідністю. Розробники часто обговорюють, коли варто використовувати PostgreSQL, а коли спеціалізовані рішення через питання масштабованості, але можна оптимізувати PostgreSQL, щоб ефективно справлятися з такими складними навантаженнями та масштабами, як петабайти — будь то події, часові ряди, аналітика в реальному часі чи векторні дані.

Ще одне поширене занепокоєння — це витрати на хмару для PostgreSQL. Торг між зручністю керування та контролем витрат є реальним питанням для розробників — тому варто звернути увагу на рівневі сховища. Архітектура рівневого зберігання Timescale пропонує практичний підхід до керування великими наборами даних у PostgreSQL, переміщуючи старіші, рідше запитувані дані в S3. Це дозволяє знизити витрати на зберігання, зберігаючи при цьому всі ваші дані доступними для запитів без зниження швидкості запитів — навіть для рідше запитуваних даних.

У цьому пості ми розглянемо, як отримати максимальну вигоду з цієї архітектури — поєднуючи високу продуктивність для нових, часто запитуваних даних з низьковартісним рівнем для старіших, менш критичних даних, при цьому зважуючи всі компроміси, щоб ви могли масштабувати свою базу даних PostgreSQL з впевненістю.

Зниження витрат на хмару для PostgreSQL: Архітектура рівневого зберігання

pic

Система рівневого зберігання Timescale створена для обробки стрімкого зростання даних часових рядів та інших вимогливих навантажень, таких як векторні дані або аналітика в реальному часі. Її архітектура поділяє дані на два рівні зберігання: високопродуктивний (для часто запитуваних даних) і низьковартісний (для рідше запитуваних), що дозволяє оптимізувати як витрати на PostgreSQL, так і його продуктивність.

1. Високопродуктивний рівень

Цей рівень зберігає ваші нові, часто запитувані дані на дисках з високою продуктивністю. Це забезпечує низьку затримку та високу пропускну здатність для читання та запису, що робить його ідеальним для навантажень, які потребують доступу в реальному часі. Останні дані, що часто запитуються, залишаються продуктивними завдяки оптимізованим індексам PostgreSQL, кешуванню та часово розділеним гиперттаблицям.

2. Низьковартісний рівень

Низьковартісний рівень призначений для старіших, рідше запитуваних даних. Використання об'єктного зберігання, як AWS S3, значно знижує витрати на зберігання, зберігаючи дані як невід'ємну частину вашої бази даних. Однак є певні компроміси: хоча старі дані залишаються повністю доступними для запитів, ви можете зазнати більш повільної реакції порівняно з високопродуктивним рівнем. Це один із аспектів, який ми нещодавно покращили, оптимізувавши продуктивність запитів для рівневих даних в 400 разів, щоб ви могли запускати складні запити на обох рівнях.

Як рівневе зберігання допомагає масштабувати PostgreSQL

Масштабованість

Система рівневого зберігання пропонує практично необмежене зберігання даних, дозволяючи вам працювати з базами даних, що зростають до петабайт, без різкого збільшення витрат.
Як ваші дані часових рядів зростають, старіші дані можуть автоматично переміщуватись до низьковартісного рівня без потреби у реорганізації бази даних або використанні зовнішніх процесів ETL (extract-load-transform).

Ефективність витрат

Зберігання даних в об'єктних сховищах, таких як S3, значно дешевше, ніж зберігання всіх даних на високопродуктивних дисках. Наприклад, низьковартісний рівень зберігання Timescale пропонує фіксовану ціну $0.021 за ГБ на місяць, що дешевше за типову тарифікацію Amazon S3. Коли ваш набір даних зростає, ця вигода від економії витрат лише збільшується.

Важливо зазначити, що на відміну від високопродуктивного рівня, ціноутворення на низьковартісний рівень розраховується за не стислу гігабайт.

Прозорі запити

Незалежно від того, де зберігаються ваші дані, архітектура Timescale робить запити безперешкодними. SQL-запити розроблені для доступу до обох рівнів без необхідності в спеціальних інструментах чи змінах у керуванні базами даних. Планувальник запитів Timescale автоматично отримує дані з відповідного рівня на основі вашого запиту за часовим діапазоном, підтримуючи єдиний інтерфейс.

Зверніть увагу, що для забезпечення безперешкодного виконання запитів до рівневих даних Timescale надає GUC (grand unified configuration) — timescaledb.enable_tiered_reads, який потрібно встановити в true. За замовчуванням він має значення false, що означає, що за замовчуванням Timescale не працює з рівневими даними. Деталі можна знайти в документації: Запити до рівневих даних.

Компроміси в продуктивності

Розуміння компромісів між високопродуктивним зберіганням і об'єктними сховищами, такими як S3, є важливим для управління продуктивністю в середовищі рівневого зберігання.

Швидкість запитів

PostgreSQL оптимізовано для запитів в реальному часі з підміліметровими часами відповіді. Однак через природу об'єктного зберігання, латентність запитів зростає для старих даних, що зберігаються в S3. Проте цей компроміс прийнятний для багатьох аналітичних навантажень або рідко запитуваних даних. Timescale гарантує, що запити, які охоплюють обидва рівні, будуть оброблятись ефективно, але швидкість високопродуктивного рівня не може бути досягнута за допомогою S3.

Цікавий GUC, який надає Timescale, це timescaledb.enable_tiered_reads. Якщо він встановлений на "false", запити отримуватимуть дані лише з високопродуктивного рівня, ігноруючи дані в низьковартісному зберіганні, як ніби їх не існує. Якщо у вашому випадку прийнятно ігнорувати дані в низьковартісному (і менш продуктивному) зберіганні, встановлення цього GUC на "false" — це один зі способів забезпечити швидкість запитів.

Витрати на зберігання

Різниця в вартості між високопродуктивним зберіганням та низьковартісним зберіганням в S3 є суттєвою. Тому зберігання великих наборів даних, які не будуть часто запитуватись, на високопродуктивному рівні є дорогим. Переміщення старих даних до S3 може зменшити цей тягар, знижуючи ваші загальні операційні витрати.

Невмотивованість проти гнучкості

PostgreSQL дозволяє виконувати вставки, оновлення та видалення в реальному часі, що є критично важливим для більшості OLTP та аналітичних додатків в реальному часі. Високопродуктивний рівень Timescale також дозволяє ці операції над стиснутими даними. Однак незмінність S3 обмежує гнучкість. Дані, переміщені на низьковартісне зберігання S3, найкраще підходять для архівних або додатків тільки з додаванням, де модифікації не очікуються.

Як оптимізувати запити через обидва рівні

Коли ви запитуєте дані, що охоплюють обидва рівні, TimescaleDB використовує свій планувальник запитів для безперешкодного отримання даних з обох рівнів. Проте продуктивність запитів може знижуватись, якщо запити не оптимізовані. Ось як можна покращити це:

Використовуйте LIMIT та ORDER BY для часткових результатів

Запити, які охоплюють обидва рівні, можуть бути оптимізовані шляхом отримання часткових результатів замість сканування всього набору даних.
Використання LIMIT разом з ORDER BY зменшує навантаження, отримуючи лише необхідну кількість рядків.

Приклад

SELECT * FROM conditions  
WHERE time_column BETWEEN '2024-01-01' AND '2024-06-01'  
ORDER BY time_column DESC  
LIMIT 100;

Пояснення

  • Цей запит отримує останні 100 точок даних з вказаного діапазону часу. За допомогою сортування результатів і обмеження рядків, запит отримує лише найновіші дані (з високопродуктивного зберігання), що дозволяє уникнути запитів до низьковартісного рівня, якщо це не потрібно.

Техніки виключення чанків для запобігання непотрібним скануванням

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

Timescale автоматично розподіляє дані на чанки за часовими інтервалами. Кожен чанк зберігає конкретний діапазон часу, тому використовуючи WHERE умову з time_column, ви можете допомогти Timescale виключити чанки, що не відповідають запиту, і уникнути непотрібних сканувань даних.

Використання умови WHERE для виключення чанків

Припустимо, ми хочемо отримати дані температури тільки для січня 2024 року. Без виключення чанків база даних може сканувати всі дані (включаючи неактуальні історичні дані), якщо запит не буде оптимізований належним чином.

Оптимізований запит з використанням WHERE для виключення чанків за часом

SELECT   
 time_column, temperature   
FROM   
 conditions  
WHERE   
 time_column BETWEEN '2024-01-01' AND '2024-01-31';

Пояснення

  • Планувальник запитів Timescale знає часовий діапазон для кожного чанка даних і буде сканувати лише чанк(и), які містять дані для січня 2024 року.
  • Чанки поза цим діапазоном, незалежно від рівня, будуть автоматично виключені, що знижує латентність запиту.

Поєднання time_bucket та умови WHERE

Ви можете поєднати функцію time_bucket з конкретним часовим діапазоном, щоб одночасно агрегувати дані та забезпечити виключення чанків.

SELECT   
 time_bucket('1 hour', time_column) AS bucket,   
 avg(temperature) AS avg_temp  
FROM   
 conditions  
WHERE   
 time_column BETWEEN '2024-03-01' AND '2024-03-31'  
GROUP BY   
 bucket;

Пояснення

  • Цей запит агрегує дані в інтервали по годині для березня 2024 року.
  • Механізм виключення чанків Timescale гарантує, що будуть скануватися лише актуальні чанки, що містять дані за березень 2024 року, уникаючи непотрібних чанків як з високопродуктивного, так і з низьковартісного рівнів.

Робота з незмінністю в низьковартісному зберіганні: стратегії та обхідні шляхи

Одним із ключових компромісів використання S3 як низьковартісного зберігання в Timescale є незмінність — після того, як дані переміщуються до низьковартісного зберігання, вони не можуть бути змінені безпосередньо. Хоча ця незмінність забезпечує стабільність і надійність даних, вона може стати проблемою, коли потрібно оновити історичні дані для доповнення або виправлення помилок.

Цей розділ обговорює стратегії роботи з незмінністю, включаючи відновлення чанків, доповнення історичних даних та використання оновлень в високопродуктивному рівні.

Доповнення історичних даних за допомогою відновлення чанків

Коли історичні дані потрібно оновити (наприклад, для виправлення помилок або додавання відсутніх даних), Timescale надає механізм, який називається відновленням чанків. Цей процес дозволяє тимчасово повернути старі дані назад до високопродуктивного рівня, де вони можуть бути змінені, а потім перенести їх назад до низьковартісного зберігання.

Робочий процес доповнення даних з відновленням чанків

  1. Ідентифікація чанка: Спочатку потрібно ідентифікувати чанк, що містить історичні дані, які потрібно змінити. Для цього потрібно виконати запит, подібний до наступного, щоб отримати правильну назву чанка:
SELECT chunk_name FROM timescaledb_information.chunks WHERE hypertable_name = 'conditions';
  1. Відновлення чанка: Використовуйте функцію untier_chunk, щоб перенести стиснуті старі дані з S3 назад до високопродуктивного зберігання.
    3.
    Модифікація даних: Після того, як чанк буде відновлений, можна виконати необхідні оновлення або доповнити відсутні дані.
  2. Повторне стиснення і повернення чанка: Після виконання оновлень, дані сжимається знову і переміщуються назад до низьковартісного зберігання.

Приклад відновлення і доповнення чанка

-- Перенести чанк з низьковартісного зберігання до високопродуктивного для модифікації  
CALL untier_chunk('_timescaledb_internal._hyper_1_1_chunk');  

-- Виконати оновлення або вставки даних  
UPDATE conditions  
SET temperature = 22.5  
WHERE time_column BETWEEN '2024-01-01' AND '2024-01-15';  

-- Після змін чанк буде стиснутий знову і повернутий до низьковартісного зберігання  
CALL retier_chunk('_timescaledb_internal._hyper_1_1_chunk');

Пояснення

  • Функція untier_chunk тимчасово переміщає чанк назад до високопродуктивного рівня для оновлень.
  • Далі ви можете змінювати дані за допомогою стандартних SQL операцій.
  • Після завершення змін, функція retier_chunk повторно стискає чанк і переміщає його назад до низьковартісного зберігання.

Коли використовувати відновлення чанків

  • Доповнення відсутніх даних: коли історичні дані потрібно оновити, щоб заповнити відсутні записи (наприклад, через неполадки датчиків у додатках Інтернету речей (IoT)).
  • Коригування історичних помилок: виправлення помилок у старих даних, які були раніше архівовані до низьковартісного зберігання.
  • Оновлення відповідно до вимог: зміна даних для дотримання нормативних вимог, особливо коли історичні записи потребують корекції.

Стадійні оновлення в високопродуктивному зберіганні

Якщо потрібно частіше оновлювати старі дані або ви хочете уникнути повторного відновлення чанків, ще однією ефективною стратегією є стадійне оновлення даних у високопродуктивному рівні перед переміщенням їх до низьковартісного зберігання. Цей підхід особливо корисний при доповненні або зміні великої кількості історичних даних.

Робочий процес стадійних оновлень

  1. Тимчасово перемістити дані до високопродуктивного рівня: Коли ви очікуєте оновлення, зберігайте дані в високопродуктивному рівні на довший час. Це дозволить легше змінювати їх без переміщення назад і вперед.
  2. Виконати оновлення або доповнення даних: Виконайте операції оновлення або доповнення, поки дані залишаються в високопродуктивному зберіганні.
  3. Повторне стиснення і переміщення даних: Після виконання всіх необхідних оновлень стисніть дані знову і перемістіть їх до низьковартісного зберігання.

Приклад стадійних оновлень даних

-- Подовжити період зберігання для високопродуктивного зберігання, щоб дозволити більше оновлень  
SELECT add_tiering_policy('conditions', INTERVAL '12 months');  

-- Виконати будь-які оновлення або доповнення для останніх даних  
UPDATE conditions  
SET temperature = temperature + 1.0  
WHERE time_column BETWEEN '2024-01-01' AND '2024-01-31';  

-- Після завершення оновлень, перемістіть дані назад до низьковартісного зберігання після оновленого періоду зберігання  
SELECT add_tiering_policy('conditions', INTERVAL '6 months');

Пояснення

  • Подовживши політику зберігання для високопродуктивного рівня, ви дозволяєте даним залишатися змінними протягом більш тривалого часу.
  • Після виконання необхідних оновлень, ви можете повернути політику зберігання, щоб перемістити дані назад до низьковартісного зберігання.

Коли використовувати стадійні оновлення в високопродуктивному рівні

  • Часті доповнення даних: Якщо ви знаєте, що конкретний набір даних потребуватиме частих оновлень, зберігання його в високопродуктивному зберіганні допоможе уникнути накладних витрат на постійне відновлення і повторне перенесення.
  • Оновлення, залежні від часу: Деякі оновлення можуть бути потрібні через регулярні інтервали (наприклад, щоквартальні коригування даних).
    Стадійне зберігання даних у високопродуктивному зберіганні перед переміщенням їх до низьковартісного забезпечує завершення всіх оновлень до фіналізації.

Обхідні стратегії для конфліктів з імунізованістю

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

Використання лише високопродуктивних таблиць для стадійного зберігання та злиття

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

Робочий процес для стадійного зберігання та злиття:

  1. Створіть тимчасову таблицю для стадійного зберігання: вставте нові або оновлені записи в окрему таблицю, яка повністю знаходиться в високопродуктивному зберіганні.
  2. Злиття з історичними даними: після того, як стадійна таблиця містить усі оновлення, злітайте нові дані в основну гіпертемплейт таблицю, відновлюючи чанки за потреби.

Приклад

-- Подовжити період зберігання для високопродуктивного зберігання, щоб дозволити більше оновлень  
SELECT add_tiering_policy('conditions', INTERVAL '12 months');  

-- Виконати будь-які оновлення або доповнення для останніх даних  
UPDATE conditions  
SET temperature = temperature + 1.0  
WHERE time_column BETWEEN '2024-01-01' AND '2024-01-31';  

-- Після завершення оновлень, перемістіть дані назад до низьковартісного зберігання після оновленого періоду зберігання  
SELECT add_tiering_policy('conditions', INTERVAL '6 months');

Переваги

  • Розділення обов'язків: стадійна таблиця дозволяє керувати оновленнями незалежно від низьковартісного зберігання, гарантуючи, що імунізованість (immutability) зберігається до необхідного моменту.
  • Мінімізація відновлення чанків: збираючи всі оновлення спочатку в стадійну таблицю високопродуктивного зберігання, ви мінімізуєте необхідність постійного відновлення чанків.

Додавання нових даних замість оновлення

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

Приклад

-- Додати нові показники температури як нові рядки замість зміни існуючих  
INSERT INTO conditions (time_column, temperature, humidity)  
VALUES ('2024-01-15', 22.5, 45.2);

Коли використовувати

  • Аудиторські сліди: у ситуаціях, коли важливо зберігати історичний запис усіх змін (наприклад, аудиторські сліди), додавання нових даних замість оновлення є природним вибором.
  • Уникнення змінюваності даних: не змінюючи існуючі записи, ви гарантуєте, що низьковартісне зберігання залишається незмінним і непошкодженим.

Кращі практики для використання багато-рівневого зберігання

1. Встановіть відповідні політики утримання даних

Одним із найважливіших аспектів використання багато-рівневого зберігання є встановлення добре продуманих політик утримання даних. Timescale дозволяє переміщати старіші дані до низьковартісного зберігання після визначеного періоду за допомогою простих SQL команд. Наприклад, ви можете автоматизувати переміщення всіх даних старших за шість місяців до низьковартісного зберігання:

SELECT add_tiering_policy ('your_hypertable', INTERVAL '6 months');

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

pic

2. Моніторинг шаблонів запитів і оптимізація переміщення рівнів

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

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

3. Стиснення для даних високопродуктивного рівня

Стиснення може значно зменшити обсяг пам'яті, що займають дані високопродуктивного рівня. Вбудований гібридний стовпцевий движок зберігання Timescale знижує використання дискового простору на 90% і більше, що зменшує витрати на зберігання навіть для високопродуктивного рівня. Дані на високопродуктивному рівні можуть залишатися стиснутими довше, при цьому забезпечуючи швидкий час відповіді на запити, що дозволяє ефективніше використовувати дорожче зберігання PostgreSQL. Це особливо корисно для часових рядів, які часто мають велику надлишковість.

Приклад:

ALTER TABLE your_hypertable SET (timescaledb.compress = true);

4. Планування компромісів S3

Хоча Timescale забезпечує прозорий доступ до даних низьковартісного рівня, важливо враховувати характеристики S3:

Імунізованість (Immutability)

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

Вища затримка

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

5. Відновлення чанків для доповнення або оновлення

Якщо потрібно оновити історичні дані, що зберігаються в низьковартісному зберіганні, Timescale надає механізм для відновлення окремих чанкiв даних, що дозволяє тимчасово переміщати їх назад до високопродуктивного зберігання. Це може бути корисно у випадках, коли необхідно виконати доповнення даних.

Приклад:

CALL untier_chunk('_Timescale_internal._hyper_1_1_chunk');

6. Оптимізація запитів для даних з кількох рівнів

При запитах, що охоплюють як нові, так і старі дані, переконайтесь, що ваші запити оптимізовані, щоб уникнути непотрібних сканувань всього набору даних. Функція виключення чанків у Timescale автоматично виключає непотрібні чанкi даних із запитів. Крім того, ефективне використання функцій SQL, таких як time_bucket, може ще більше оптимізувати продуктивність.

7. Розумне використання реплікації даних

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

Висновок

Много-рівневе зберігання Timescale поєднує продуктивність PostgreSQL та економію витрат на об'єктне зберігання в хмарі, таке як S3, що робить його ідеальним рішенням для даних часових рядів та складних навантажень у масштабах. Ефективно керуючи політиками рівнів зберігання, використовуючи стиснення і розуміючи компроміси між високопродуктивним і низьковартісним зберіганням даних, ви можете оптимізувати своє розгортання Timescale для обробки зростаючих наборів даних з легкістю, одночасно контролюючи витрати на хмарне зберігання.

Впровадження цих кращих практик допоможе знайти правильний баланс між продуктивністю та витратами, забезпечуючи ефективність і масштабованість ваших навантажень часового ряду на довгострокову перспективу.
Для подальшого читання обов'язково ознайомтесь з цією статтею про Масштабування PostgreSQL до масштабу петабайт з використанням архітектури багаторівневого зберігання Timescale.

Багаторівневе зберігання доступне лише в хмарній платформі PostgreSQL від Timescale, Timescale Cloud. Почніть безкоштовно тут (не потрібно вказувати кредитну картку, безкоштовно на 30 днів).

Цю статтю написав Умаїр Шахід і вона була спочатку опублікована тут на офіційному блозі Timescale 17 січня 2025 року.

Перекладено з: How to Optimize PostgreSQL Cloud Costs With Tiered Storage

Leave a Reply

Your email address will not be published. Required fields are marked *