Як управляти 3,1 мільярдами рядків даних?


14

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

Нещодавно було додано вимогу для відстеження значення min/ max/ sumза минулу годину.

ПРИМІТКА: В ідеалі я хотів би розглянути варіант MongoDB, але мені потрібно продемонструвати, що я спочатку вичерпав параметри SQL-сервера.

Дані

Наступна таблиця представляє первинне джерело даних (найчастіше запитується). У таблиці буде приблизно п’ять мільйонів рядків. Зміни даних будуть переважно UPDATEвисловлюваннями з дуже випадковими INSERTтвердженнями після початкового завантаження даних. Я вирішив кластерувати дані, dataPointIdяк ви завжди будете вибирати all values for a given data point.

// Simplified Table
CREATE TABLE [dbo].[DataPointValue](
    [dataPointId]  [int] NOT NULL,
    [valueId]      [int] NOT NULL,
    [timestamp]    [datetime] NOT NULL,
    [minimum]      [decimal](18, 0) NOT NULL,
    [hourMinimum]  [decimal](18, 0) NOT NULL,
    [current]      [decimal](18, 0) NOT NULL,
    [currentTrend] [decimal](18, 0) NOT NULL,
    [hourMaximum]  [decimal](18, 0) NOT NULL,
    [maximum]      [decimal](18, 0) NOT NULL

    CONSTRAINT [PK_MeterDataPointValue] PRIMARY KEY CLUSTERED ([dataPointId],[valueId])
)

Друга таблиця помітно більша - приблизно 3,1 мільярда рядків (що представляє дані за останні шість місяців). Дані, старші ніж шість місяців, будуть очищені; в іншому випадку суворо INSERTтвердження даних (~ 200 рядків / сек, 720 000 рядків / годину, 17 мільйонів рядків на тиждень).

// Simplified Table
CREATE TABLE [dbo].[DataPointValueHistory](
    [dataPointId] [int]            NOT NULL,
    [valueId]     [int]            NOT NULL,
    [timestamp]   [datetime]       NOT NULL,
    [value]       [decimal](18, 0) NOT NULL,
    [delta]       [decimal](18, 0) NOT NULL

    CONSTRAINT [PK_MeterDataPointHistory] PRIMARY KEY CLUSTERED ([dataPointId], [valueId], [timestamp])

)

Очікується, що ця таблиця збільшиться удвічі за розмірами, оскільки кількість відстежених значень точки даних зросте до 400 рядків / сек (тому досягнення ~ 10 мільярдів не підлягає сумніву).

Питання (-и) я задаю більше одного ... вони тісно пов'язані між собою).

На даний момент я використовую базу даних SQL-Server 2008 R2 Standard Edition. Я, швидше за все, зроблю справу для оновлення до Enterprise Edition, якщо зможете отримати бажаний рівень продуктивності за допомогою розділів таблиці (або MongoDB, якщо не вдасться досягти необхідних рівнів продуктивності за допомогою SQL-Server). Я хотів би ваш внесок щодо наступного:


1) Враховуючи, що мені потрібно обчислити min, maxі sumза минулу годину (як в now - 60 minutes). Який найкращий підхід для відстеження останніх даних:

  • Зберігайте останні дані в пам'яті служби передачі даних. Випишіть обчислені хв / макс / середнє значення з кожним оновленням даних.

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

  • Збережіть недавню історію в самому рядку DataPointValue, щоб уникнути пошуку таблиці історії? Можливо, зберігається у вигляді обмеженого рядка та обробляється всередині облікового запису UPDATE?

  • Інший варіант, який я не розглядав?


2) Для DataPointValueHistory, запити до даних, які завжди будуть, будуть dataPointIdабо однією або кількома запитами valueId. Запитані дані, як правило, припадають на останній день, тиждень або місяць, але в деяких випадках можуть бути цілі шість місяців.

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

  • Кластер DataPointValueHistoryпо dataPointId -> valueId -> timeStamp

  • Кластер DataPointValueHistoryза часомStamp -> dataPointId -> valueId


3) Нарешті, як було сказано вище, я думаю, що буде сенс розділити DataPointValueHistoryтаблицю. Будемо дуже вдячні за будь-які пропозиції щодо найкращого розподілу даних історії.

  • Якщо спочатку кластеризовано часовою міткою, я думаю, що дані слід розподілити за тижнями (всього 27 розділів). Найдавніша перегородка буде очищена після 27 тижня.

  • Якщо спочатку згруповано dataPointId, я думаю, що дані повинні бути розділені деяким модулем ідентифікатора?

Оскільки у мене дуже обмежений досвід роботи з розділеннями таблиць, ваш досвід буде вдячний.


Ви видалили версію цього питання в StackOverflow?
Taryn

@bluefeet - Так, це було позначено як поза темою ... тому я видалив питання ТА і створив його знову (я, мабуть, зачекав, щоб його перенесли).
Калгарі Кодер

Немає проблем, я просто переконався, що у нас не було запитань із перекладом.
Taryn

У стандартній версії ви все ще можете розділити дані за допомогою розділених представлень та кількох базових таблиць. Не впевнений, якщо ви це врахували.
Джон Сейгель

@Jon - Так, я розглядав розділи таблиці вручну (цей конкретний вибір ґрунтується на тому, чи є в наявності ліцензія Enterprise ... якщо так, то чому я мою роль).
Калгарі Кодер

Відповіді:


4

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

http://leiliweb.wordpress.com/2012/12/11/partified-table-and-index-strategies-using-sql-server-2008/


Дякую за посилання, безумовно, корисне ... будь-які думки щодо пункту 1 чи 2?
Калгарі Кодер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.