MongoDb и память
Монга, насколько я помню, хранит индексы в памяти целиком, стоит посмотреть, сколько они занимают по сравнению со всей памятью (db.mycollection.totalIndexSize хотя сомневаюсь, что много).
repairDatabase — это очень и очень медленно, помогает если у тебя было много вспомогательных коллекций и записей, которые ты потом подропал.
Что говорит db.serverStatus.mem ?
1 SELECT a, b, c, rating * if(a=$VAR1, 1, 10) AS rating FROM tablename WHERE b = $VAR2 ORDER BY rating DESC LIMIT $VAR3для такого запроса скорее нужна материализованная вьюха (или таблица-кэш, которая руками обновляется, при изменении основной таблицы чем nosql
Данные по серверу не покажу, потому что уже базу дропнул)
Впрочем, судя по всему, виной всему является то, что сервер оказался последней выжившей виртуалкой на OpenVZ, будь оно неладно. Буду переносить на нормальный сервер и смотреть.
Почему не используешь redis/memcached?
для такого запроса скорее нужна материализованная вьюха (или таблица-кэш, которая руками обновляется, при изменении основной таблицы чем nosqlВот вся идея в том, что это УЖЕ и есть специальная таблица-кэш. Поле b ($VAR1) является ключом кэша, но оно может давать вплоть до 2к результатов. Мне надо, соответственно, только около 15 «самых релевантных». Чтобы не гонять все 2к результатов из мускуля на клиент, я и модифицирую rating (a=$VAR2 с последующей сортировкой.
Мне вот кажется, что это в принципе больше соответствует идее nosql. Но пока хочу изучить, будет ли выигрыш в производительности.
Почему не используешь redis/memcached?Потому что у мемкэшеда придётся всю сортировку и лимиты переносить на клиент (см. ответ 'у а редис — потому что посмотрел обзоры nosql и решил сначала попробовать монго. Ну и, у редиса, насколько я понимаю, опять-таки придётся часть функционала переносить на клиент.
Мне вот кажется, что это в принципе больше соответствует идее nosql.Можно пояснить для тупых?
Насколько я понимаю идею nosql — быстрым в nosql БД будет доступ к единичным объектам, коих может быть очень много.
В этой задачке, вроде Indexes in MongoDB are conceptually similar to those in RDBMSes like MySQL. You will want an index in MongoDB in the same sort of situations where you would have wanted an index in MySQL .
Т.е. непонятно чем принципиально NoSQL может быть быстрее — идея не помогает тут быстродействию (?)
Идея в том, что мы по имеем KV-хранилище → выборка всегда идёт просто по ключу → нет никаких затрат на разбор запроса. Мы базе ключ, она нам значения. Никакой компиляции запроса, связей между таблицами и ничего подобного.
Мы базе ключ, она нам значения. Никакой компиляции запроса, связей между таблицами и ничего подобного.на этой задаче как раз быстро работают табличные базы (они же sql).
nosql хорошо работает, когда в запросе куча join-ов по индексам, их nosql заменяет на прямые ссылки, и это сильно ускоряет запросы.
O_o. Поясните
Я тоже не очень понял. Половина nosql-решений вообще вроде же не умеют "джоинов", нет?
Идея в том, что мы по имеем KV-хранилище → выборка всегда идёт просто по ключу → нет никаких затрат на разбор запроса.Где тут "выборка по ключу"?
WHERE b = $VAR2 ORDER BY rating DESC LIMIT $VAR3
например,
user
name <name>
phone <phone1>, mobile
phone <phone2>, home
..
phone <phoneN-1>, work
phone <phoneN>, work
чтобы хранить такую структуру в реляционной-базе, необходимо, как минимум две таблицы: user и phone.
и при получении такого юзера из базы появляется join, что достаточно накладно, если, например, стоит задача выдернуть 100 "произвольных" пользователей целиком со всеми их телефонами (или хотя бы первыми тремя)
nosql базы позволяют ограничиться одной "таблицей", в которой юзер хранится целиком, как одно "значение".
соответственно, при запросе из такой базы - join уже не нужен, он автоматически заменился на прямые ссылки, и производительность вырастает.
зы
ms sql и oracle, кстати, позволяют тоже обойтись одной таблицей, если перейти на частичное хранение данных в виде xml-я.
соответственно, никакой "магии" в них нет, а есть все те же недостатки и преимущества отличия сетевых баз от реляционных
и при получении такого юзера из базы появляется join, что достаточно накладно, если, например, стоит задача выдернуть 100 "произвольных" пользователей целиком со всеми их телефонами (или хотя бы первыми тремя)view тут чем не годится?
view тут чем не годится?расшифруй.
интересует, что возвращает вью (какая схема данных а во-вторых, куда денется join?
интересует, что возвращает вью (какая схема данных а во-вторых, куда денется join?А в чем проблема во view с join'ами ?
А в чем проблема во view с join'ами ?ты сейчас говоришь про то, что между кодом и субд можно сделать один запрос (сделав вью или процедуру) - это очевидная оптимизация.
но эта оптимизация от самого join-а не избавляется, а тормозит именно он, особенно если не удалось таблицы целиком в память поднять.
это связано с тем, что если для самих 100 "произвольных" юзеров можно добиться с помощью индексов, чтобы они лежали последовательно (в одном или смежных секторах диска то телефоны ста таких юзеров, уже будут раскиданы по куче секторов, если таблица телефонов большая.
а подъем ста разбросанных секторов с винта - это уже очень долгая операция, головки передвигаются не очень быстро.
зы
даже если винт заменяется на SSD или на память, то всё ускоряется, но все равно остается верным утверждение:
выборка последовательных записей на порядок-два быстрее, чем выборка разнесенных далеко находящихся друг от друга записей.
но эта оптимизация от самого join-а не избавляется, а тормозит именно он, особенно если не удалось таблицы целиком в память поднять.Кагбы виден намек почему МонгоДБ память-то выел, не?
http://wiki.postgresql.org/wiki/Materialized_Views — есть способы заниматься этим в реляционной БД. Повторюсь, опять же, что NoSQL этой проблемы никаким магическим способом не решает, проблема остается.
Решать ее проще в реляционной БД (вроде потому как для выборок и работы с массивами данных NoSQL не предназначен, а тут после where как раз такое безобразие и идет.
выборка последовательных записей на порядок-два быстрее, чем выборка разнесенных далеко находящихся друг от друга записей.Чем тут поможет MongoDB?
http://wiki.postgresql.org/wiki/Materialized_Views — есть способы заниматься этим в реляционной БД.ок.
есть схема данных:
user
name <name>
phone <phone1>, <kind>
..
phone <phoneN>, <kind>
age <age>
необходимо обеспечить быстрое выполнение запросов под paging с сортировкой по имени при фильтрации по возрасту, по каждому юзеру выводятся name, age и первых три телефона (с приоритизацией сначала мобильный, потом рабочий, потом домашний)
в ооп-нотации - это будет что-то типа:
users
.Where(user => user.age >= min-age && user.age <= min-age)
.OrderBy(user => user.name)
.Select(user => new User(name=user.name, phones=user.phones.OrderBy(phone => phone.kind-priority).Take(3 age=user.age
.Skip(page-number * page-count)
.Take(page-count)
как под эту задачу будет выглядеть материализованный вью?
Чем тут поможет MongoDB?т.к. она иерархическая, то все телефоны одного юзера будет лежать рядом.
соответственно, если сами юзеры лежат рядом, то и их телефоны тоже будет рядом лежать.
Где тут "выборка по ключу"?b — ключ. Выбираем по ключу. Дальше мы сортируем уже результат. Что не так?
WHERE b = $VAR2 ORDER BY rating DESC LIMIT $VAR3
возьмем произвольную структуру данных один ко многим:А если не нормализовать таблицу то join не нужен. тогда непонятно преимущество nosql
например,
user
name <name>
phone <phone1>, mobile
phone <phone2>, home
..
т.к. она иерархическая, то все телефоны одного юзера будет лежать рядом.Индексы не за этим придуманы?
соответственно, если сами юзеры лежат рядом, то и их телефоны тоже будет рядом лежать.
как под эту задачу будет выглядеть материализованный вью?name, age, tel1, tel2, tel3
Дальше нужно посмотреть какие индексы лучше работают. Ты поясни какая магия в МонгоДБ эту ситуацию обработает лучше — там примерно такая же логика работы будет, только менее продвинутая, поскольку до постгреса ей пилить и пилить.
А если не нормализовать таблицу то join не нужен.лучше, конечно, такую ненормализованную таблицу создавать через материализованный вью из нормализованный данных, как выше уже намекает No.
это упростит задачу поддержания целостности.
да, такой подход можно использовать для уменьшения кол-ва join-ов
Ты поясни какая магия в МонгоДБ эту ситуацию обработает лучшеструктура иерархического хранения данных
name, age, tel1, tel2, tel3а переворачивать как будешь телефоны из записей в колонки? при условии, что там поле телефона все-таки не одно, а их там несколько штук
структура иерархического хранения данныхОк, ждем ответа про индексы.
Иерархически в Монге устроены только документы, если не путаю. Как там данные хранятся — дай ссылку? Имхо там такие же механизмы с индексами.
Ок, ждем ответа про индексы.для начала ответь, чем иерархический индекс отличается от индекса в реляционной базе.
> Имхо там такие же механизмы с индексами.
да, там тоже индексы, но иерархические, вложенные в друг друга
а переворачивать как будешь телефоны из записей в колонки?Не понимаю я вашего языка Чего надо делать?
для начала ответь, чем иерархический индекс отличается от индекса в реляционной базе.ничем
Я так и не понял, у тебя в монге мильен объектов с теми же свойствами name, age, tel1, tel2, tel3 . Как она по ним заметно быстрее искать будет чем постгрес? Напиши плз.
Это ты такую гениальную структуру собираешься в монге делать?
у тебя в монге мильен объектов с теми же свойствами name, age, tel1, tel2, tel3
ничемпо ссылке - не иерархический индекс.
по ссылке хранение данных, имеющих иерархические отношения, поверх плоского индекса.
1. Опиши как работает МонгоДБ на данной задаче и с какими объектами и за счет чего ожидается прирост скорости. Имхо там не будет ничего такого что не реализуется на постгресе с примерно такими же затратами, если не лучше.
2. Ничего не нашел про иерархические индексы в МонгоДБ, они там те же B-tree, как и в Постгресе. Дай ссылку плз. В постгресе есть индексы для работы с иерархиями тем не менее.
это и будет иерархический индекс.
hint: btree-телефонов данного юзера можно вложить внутрь записи юзера, которая находится внутри btree-юзеров.Спасибо, капитан. Ты решение задачи опиши сначала.
Спасибо, капитан. Ты решение задачи опиши сначала.оно очевидно, если перечитать hint
оно очевидно, если перечитать hintПеречитай и осознай что, очевидно, на постгресе задачка решается проще.
Оставить комментарий
doublemother
Есть ситуация: есть некий сервер с N гигабайт памяти. Есть база, которая в мускуле со всеми индексами весила K<N гигабайт, но мы решили попробовать завести монго, и теперь она весит M>N гигабайт.Проблемы начались уже при заполнении базы — в какой-то момент выжралась вся память и коннекты, заполняющие базу, подропались. Ладно, у нас есть база, пусть и не со всеми записями. Которая жрёт всю память на машине. Если поискать по интернетам, то разработчики монго говорят, что "те, кто говорят, что монго жрёт память, это просто парни, которые не шарят в мемори менеджменте. Мы юзаем клёвый mmap, и система сама освобождает память, когда надо".
Я понимаю, что в теории всё круто. На практике это означает, что, например, крутится у меня в консоли в watch скрипт (ps|grep и в какой-то момент он умирает со словами типа "cannot fork".
Подропал коллекции, смотрю, база по-прежнему много места жрёт, делаю из монго-шелла db.repairDatabase. Память съелась ВСЯ. То есть, я не смог из соседнего запущенного шелла даже ls, ps, free, kill и т.п. сделать. Убил монго-шелл, ничего не изменилось. Памяти на хосте нет вообще, убить монго не могу. После того, как все шеллы разлогинил, памяти не прибавилось, шелл не запустить, на хост ssh сделать нельзя — жду теперь, чтобы админы машину ребутнули.
Кто с монго сталкивался, вы встречали такие проблемы, и если да, то как решали?
Другие какие-нибудь nosql-решения кто-нибудь может посоветовать? Основное, что предполагается делать — аналог sql-ного запроса: