2015-08-10 4 views
2

Я запускаю рубин на Rails-приложении с бэкэнд PostgreSQL, и мне интересно, какой стандартный способ хранить серию временных меток. Ситуация в том, что у меня есть модель с логическим атрибутом status. Мне нужно отслеживать даты/время изменения этого атрибута, потому что мне нужно отслеживать периоды времени, в течение которых status установлено на true. Мой опыт с подобными проблемами серьезно отсутствует, и я не уверен, что наилучшая практика заключается в том, чтобы делать такие вещи масштабируемым образом. Два подхода, которые я рассмотрел, следующие:Хранение активных/неактивных временных меток

1) JSONifying text. Я думал о принятии массива, который может выглядеть следующим образом:

[ 
    { 
     start: "20150131103045", 
     end: "20150228103045" 
    }, 
    { 
     start: "20150531103045", 
     end: "20150628103045" 
    }, 
] 

Я бы тогда JSONify этого массив и хранить его в text колонки.

2) Создание отдельной таблицы, которая будет иметь столбцы model_id, status и time_recorded атрибутов, а затем просто создание записи каждый раз, когда атрибут модели status обновляется.

Какой из этих подходов более звучит? Что-то, чтобы рассмотреть здесь, состоит в том, что эти данные, вероятно, не будут читаться очень часто - в 95% случаев это будут только новые данные, которые будут записаны в базу данных.

Вариант 1) кажется менее тяжелым для меня, но также было бы больнее читать данные и сортировать их, когда мне нужно. Вариант 2) сохранит эти данные таким образом, с которым легче работать, и уже существующие данные никогда не нуждаются в чтении/обновлении, но таблица может быть очень большой, очень быстро. Кикер - это то, что я должен сделать это с несколькими моделями в моем приложении, поэтому принятие поспешного решения и реализация плохой архитектуры с самого начала может быть довольно раздражающим, чтобы иметь дело позже.

Каковы плюсы и минусы этих двух подходов? Является ли это одним из лучших решений, чем другое? Или есть другой, лучший вариант, о котором я не думал?

ответ

1

Вариант 1:

Вы должны учитывать при выполнении обновления в ряд, Postgres будет в фоновом режиме создать еще одну версию этой строки, с новыми данными на нем, и отметьте старый быть повторно когда в этой таблице сделан вакуум. Как вы можете видеть, это вызовет много «усилий по вакууму» (прочитайте его как высокую нагрузку на диск/IO). Это будет даже хуже, если данные строки не помещаются на одной странице данных. В этом случае также есть таблица «тостов», которую нужно очистить.


Вариант 2:

Это выглядит для меня лучший подход, потому что, когда строка вставляется, вы никогда не будете обновлять его. И данные выглядят достаточно маленькими, чтобы соответствовать одной странице данных (нет необходимости в таблице тостов). Если вы используете правильные индексы, у вас не будет проблем с производительностью. Postgres может легко обрабатывать миллионы записей.

Также вы можете использовать технику patitioning table. Если в таблице есть миллиарды и миллиарды записей истории, вы можете «разбить» ее на несколько других таблиц (например, один месяц), где индексы будут довольно маленькими за стол и будут работать очень быстро. Все сделано в фоновом режиме, поэтому ваше приложение увидит только «главную» таблицу, и Postgres автоматически будет обрабатывать все остальные таблицы сплайсинга.

Если вам нужно получить данные в формате JSON, это тоже будет легко. Вы можете просто создать представление (или функцию, если хотите), где этот столбец со временем начала/окончания будет установлен в формате массива JSON (с использованием postgres 9.3 и выше).

Смежные вопросы