LINUX.ORG.RU

База данных и тучи апдейтов или нужен свежий взгляд на проблему

 , , ,


0

2

Господа, имеется реальная, сложная задача по БД. Конечно, возможно я заработался и не вижу лёгкого подхода, но за тем и прошу совета.

Ситуация такова: имеется объект в Postgre. Количество, на данный момент - 20 тысяч. Однако это даже не 1% процент от того, что набежит за несколько месяцев в продакшне.

По каждому объекту собирается статистика за каждый день, что есть отдельный объект, добро это хранится в MongoDB. Потому что объёмы большие, нереально большие на инсерты и апдейты, но не на селекты. Логика такова, что статистика за текущий день пересчитывается каждые 30 минут и может меняться в + или в -. Такая же ситуация со статистикой за предыдущие дни, только пересчитывается она редко.

Каждый объект в постгре отображается пользователю и необходимо просчитывать для него статистику за месяц, неделю, всё время. Благо есть пагинация и единовременно необходимо отдавать до 50 объектов, просчитать это довольно просто - 3 MapReduce запроса на каждый объект.

Проблема в том, что необходимо реализовывать такие вещи, как сортировка и фильтрация. Это не говоря уже о том, что если захочется отображать, например, 1000 объектов, то хорошо бы иметь статистику сразу.

Задача понятна - нужно просчитывать статистику и хранить её в БД, кешировать. Например, раз в час. Однако, мы имеем, скажем, 3 млн объектов и по каждому мы должны сделать, пока, 3 MapReduce в MongoDB и 1 Update в Postgre.

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

Какие мысли, идеи? Буду рад любым советам.


Ну если у тебя данные из монго берутся и не страшно данные потерять (в том плане, что их можно легко восстановить) то можно побаловаться такими настройками -

fsync=off
synchronous_commit=off
full_page_writes=off
bgwriter_lru_maxpages=0
postgres будет быстрее монги.

pi11 ★★★★★
()
Последнее исправление: pi11 (всего исправлений: 1)

Плюс если у тебя редкие селекты, то может быть просто пересчитывать только когда запрашиваются данные и они устарели?

Или все 3 миллиона объектов каждый час будут просматриваться?

pi11 ★★★★★
()
Ответ на: комментарий от pi11

При сортировке и фильтрации мы же будем обязаны иметь всю эту информацию, иначе никак.

Думаешь что если статистику хранить в постгре, то всё будет быстрее? На триггерах можно, кстати, попробовать, но эффективно ли это всё будет?

Пугает что если делать постгре, то с 3млн записями, за год, накопится 1 миллиард 95 миллионов записей. Ходят слухи что монга с таким справится, а вот постгре - нет. Правду ли молвят?

tia
() автор топика
Ответ на: комментарий от pi11

Если я правильно понял, то это именно на случай, если данные в монгу и будут класться. Проблема то в том, что нужно класть в постгре. Конечно, как вариант, можно кешировать в монгу(будет две сущности для каждого объекта, при этом работа будет идти со второй, кешем, что мне не очень нравится).

tia
() автор топика
Ответ на: комментарий от tia

слухи что монга с таким справится

Я тоже слышал о ней слухи, и о потерях при полгигабайте данных и о стабильности.

1 миллиард 95 миллионов записей

Сколько данных-то в байтах? Смотря что значит «справится», одно дело селект по первичному ключу горячих данных, другое - постоянно лазить за историческими

disarmer ★★★
()
Ответ на: комментарий от disarmer

Структура примерно такая:

AID: LongInt
BID: LongInt
Stat1: Int
Stat2: Int
Stat3: Int
Day: DateTime(JS-объект, надо смотреть как хранится он в BSON).

Собственно, вот такая вот статистика. Но окей, а что скажешь о постгре? Погуглю конечно, но не кажется мне что там можно хранить такие объёмы. Может тогда какую ещё БД посоветуешь?

tia
() автор топика
Ответ на: комментарий от tia

Не знаю с таким количеством записей не работал с постгресом. 200млн - легко ворочает на среднем сервачке.

Монга быстра за счет того что в памяти сидит. Постгрес тоже можно по максимому в память засунуть.

pi11 ★★★★★
()
Последнее исправление: pi11 (всего исправлений: 1)
Ответ на: комментарий от tia

Получается несколько байт на кортеж(не знаю сколько занимает Day: DateTime). У postgres минимальный оверхед на кортеж, ЕМНИП - 24 байта. То есть служебных данных будет больше чем реальных.

Но мой вопрос не о том, сколько данных получается на кортеж с учётом оверхеда/индексов? Можно прикинуть разделив размер таблицы в байтах на количество кортежей. Потом умножить среднюю длину кортежа на предполагаемый рост (1 миллиард 95 миллионов записей), оттуда уже смотреть, влезет ли это на одну машину.

И количество данных тоже не прямо влияет на производительность, нужно знать характер приложения, соотношение чтения/записи, откуда происходят выборки (то есть будут ли данные, к которым редко обращаются?). Это даст идеи для шардирования.

Ну и нужно знать по каким полям в основном происходит выборка, думать о индексах.

не кажется мне что там можно хранить такие объёмы.

Хранить - можно. Только запросы тормозить будут.

Может тогда какую ещё БД посоветуешь?

А нету больше БД, одни k/v и nosql поделки кругом. Есть еще oracle, но он не лучше

disarmer ★★★
()
Ответ на: комментарий от disarmer

Можно предположить что влезет на одну машинку, шардировать - уже немного другой вопрос. Разница с влезет/не влезет только в том, как оно часто будет лезть в своп и хватит ли скорости SSD'шек, как я понимаю. А это всё можно регулировать. Дело в том, что сейчас интересует как бы именно в коде и бд сделать так, чтобы без лишних проблем можно было скалироваться. Предположим что пока только вертикально.

Со статистикой всё просто: мы читаем только для того, чтобы суммировать данные за промежуток времени(одни и те же), а если кешировать, то обращение будет только к кешу. Раз в 30 минут идёт обращение на запись(апдейт с апсеротом(инсерт при отсутствии записи)) в монгу одной-двух записей статистики на каждый объект.

На сколько я знаю, в Постгре каждый запрос лочит соединение, пока не будет выполнен(хотя вот в транзакциях слышал что инсерты и апдейты проходят без ожидания, но зато при коммите придётся ждать), когда монга просто съедает их и кидает в очередь, как я понимаю. Здесь получается у монги плюс при большом числе апдейтов/инсертов. Но удобнее, конечно, было бы с постгре, да вот делать 3млн апдейтов каждый час... мне страшновато.

tia
() автор топика
Ответ на: комментарий от pi11

У меня больше проблема в том, как сихронизировать кеширование суммы по статистике, как оптимизовать его. Но 200млн записей это круто... У меня простая виртуалка с 40млн дохла и постгре уже мог по минут 10-30 выполнять простые запросы. Хотя уже не помню, может налажал там много.

tia
() автор топика
Ответ на: комментарий от tia

в Постгре каждый запрос лочит соединение, пока не будет выполнен

Протокол такой, да. И все мелкие insert/update тормозят на коммите, потому что ждут сброса на диск, лечится это отключением синхронного коммита:

SET synchronous_commit TO OFF

Я не очень понял из описания, вы хотите хранить N-гигабайт данных в postgresql и такую же по размеру копию в mongo в качестве кеша?

У всех объектов в базе будет обновляться статистика?

Раз в 30 минут идёт обращение на запись

при потере питания, зависаниях и прочем потеряется до 30 минут последних изменений, это ок?

Почитайте про массовую загрузку(в частности COPY), 3 миллиона в час это не так много: http://www.postgresql.org/docs/9.3/static/populate.html

disarmer ★★★
()
Ответ на: комментарий от tia

Может тогда какую ещё БД посоветуешь?

Если реляционность не важна и сойдёт k/v, есть еще elliptics, как раз заточенный на большие объёмы мелких ключей. Но у него маленькое community, и нужно вникать для использования

disarmer ★★★
()
Ответ на: комментарий от disarmer

1) информация о объектах, постгре. Простые структуры, на самом деле.
2) статистика, монга (структуры, представленные выше). Число структур = число дней, за которое ведётся статистика * число объектов
3) Кешированная сумма статистических данных, монга/постгре(не определился делать ли коллекцию в монге, либо пихать в информацию о объекте(см п.1)). Равно числу объектов.

Раз в 30 минут идёт просто сбор накопленных данных с другого сервера(имеется только API, данные можно собрать только за последние дни). Так что допускается даже если статистика будет отсутствовать за последние дня 4, её можно пересобрать. Для актуальности общей картины был выбран интервал в 30 минут.

Что по обновлению, то нужно будет сравнивать изменилась ли статистика, а тогда нужно будет делать запрос на получение предыдущей статистики из монги. В теории, можно и правда минимизировать число объектов, для которых статистика обновилась, таким вот способом. Подумаю на этот счёт, огромное спасибо.

А будет ли от COPY толк? Подразумевается что я могу инсертить сразу все данные во временную таблицу, не делая селекты, тогда это будет быстрее апдейтов?

tia
() автор топика
Ответ на: комментарий от disarmer

Мне может пригодиться это разве что если он умеет одну из двух вещей:
1) Быструю агрегацию(для ускорения суммирования статистических данных по объектам), тогда статистику можно запихнуть туда
2) Сортировку+фильтрацию+быструю запись без лока(для хранения кешированных данных по объектам или, может быть, даже самих объектов), ибо всё это крайне важно.

tia
() автор топика
Ответ на: комментарий от tia

Если ты беспокоишься насчёт вставки, то есть всякие очереди типа pgpool-II

wyldrodney
()
Ответ на: комментарий от tia

А будет ли от COPY толк?

Толк будет на большом количестве одновременных insert. Тогда update нужно делать отдельно.

Есть еще вариант, можно вообще не хранить историю в БД, только писать в логи и обновлять каждые полчаса аггрегированные данные в postgres, если для их расчёта не нужны все исторические данные (типа сумма, среднее значение). Графики-отчёты можно и по логам рисовать.

disarmer ★★★
()

Если у тебя там Trades and Quotes, то используй kdb+, как все нормальные люди.

32-битная версия, которой тебе с 30M/день хватит за глаза, теперь полностью бесплатна.

http://kx.com

anonymous
()

Задача понятна - нужно просчитывать статистику и хранить её в БД

Можно, и даже нужно хранить только те результаты, которые получаются за счет аггрегаций, типа COUNT, AVG, HAVING, тогда при выводе брать готовые результаты аггрегации и джойнить к фильтрам. Шевелиться точно будет быстрее и места займет меньше, но тут я хз конкретно по задачам, может в некоторых фильтрах не прокатить такой выверт.

Как вариант, гнать в ту же MongoDB

Как вменяемый вариант - горизонтальное масштабирование и master/slave коннекты.

deep-purple ★★★★★
()

Я бы рекомендовал сначала провести нагрузочное тестирование, что б выявить узкие места, иначе голимая угадайка, если у вас приложение не выживет на 40000 записей можно до посинения тюнить БД. Вариантов то масса.

Как пишут выше нужно знать насколько критична потеря данный, можно играться с настройками записи / транзакционностью.

Если данные по одному объекту запрашиваются раз в неделю нет смысла считать статистику каждые .5 часа. Если при обращении кеш устарел - считаем, иначе по крону например раз в сутки в промежутки времени с низкой нагрузкой.

Переезд на SSD/более мощное железо.

Если нет необходимости делать сложные выборки можно предусмотреть возможность работы с несколькми инстансами постгре.

Способы не взаимоисключающие.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.