Кэширование данных EAV — XML или NoSQL/MongoDB?

Я создаю веб-приложение, которое в значительной степени зависит от EAV. шаблон для хранения данных. В основном это означает, что каждый атрибут объекта имеет свою собственную строку в массивной таблице базы данных. Я использую MySQL для хранения всего. Это очень упрощенный пример того, что я храню...

OBJECTS              ATTRIBUTES

objId | type         objId | attribute | value
=============        =========================
1     | fruit        1     | color     | green 
2     | fruit        1     | shape     | round
3     | book         2     | color     | red

Я знаю, что некоторые люди ненавидят EAV, но мне нужно иметь возможность произвольно добавлять новые атрибуты объекта, не изменяя схему базы данных, и до сих пор у меня это работало очень хорошо.

Как я думаю, кто-нибудь еще обнаружит при построении системы с использованием структуры данных EAV, слабость этого подхода заключается в извлечении нескольких объектов вместе с атрибутами каждого объекта. На данный момент мое приложение отображает только 10 объектов за раз, поэтому я просто запрашиваю свою таблицу EAV 10 раз (один раз для каждого объекта), и это все еще очень быстро. Однако я хотел бы снять это ограничение и разрешить извлечение сотен объектов за один раз. Я также хочу иметь возможность запрашивать объекты более гибким способом, чем сейчас.

Делать это с помощью соединений SQL было бы отвратительно, поэтому я рассматриваю возможность кэширования данных. В среднем база данных получает около 300 чтений на каждую 1 запись, поэтому я думаю, что это хороший кандидат для кэширования.

Пока такие варианты я придумал...

  1. Столбец базы данных XML: каждый раз при выполнении записи обновляйте текстовый столбец XML в таблице objects, содержащий все атрибуты объекта. Это будет работать для быстрого чтения данных, но запрос XML-данных, скрытых в таблице базы данных, запутан.

  2. Файл XML: каждый раз, когда выполняется запись, записывайте файл XML на диск, который содержит каждый объект и его атрибуты. Преимущество этого заключается в том, что я могу затем использовать XQuery для запроса объектов.

  3. NoSQL (например, MongoDB): Возможно, мне следовало построить систему на бессхемной базе данных, такой как MongoDB. Переписывание всего приложения для использования MongoDB заняло бы довольно много времени, но меня осенило, что я могу использовать его в качестве кэша. Так, например, каждый раз, когда данные записываются в хранилище EAV, эквивалентный объект будет обновляться в MongoDB, который затем будет использоваться для чтения и запросов.

Первоначально я думал, что файл XML будет лучшим подходом, но я вижу, что файл становится действительно большим и неуправляемым. На данный момент я склоняюсь к использованию MongoDB. Я знаю, что использование двух серверов баз данных для одного приложения кажется безумием, но я думаю, что это может сработать в моем случае.

Я хотел бы услышать ваши мысли по этому поводу.


person philwilks    schedule 25.01.2012    source источник
comment
PS: Я только что вспомнил четвертый вариант. В будущем мне нужно добавить в приложение средство полнотекстового поиска, для чего я рассматривал возможность использования Apache Lucene. Поскольку я собираюсь обновлять индекс Lucene при каждой записи в базу данных, возможно, это можно использовать для других операций чтения, не связанных строго с поиском, например, просто для перечисления всех объектов определенного типа.   -  person philwilks    schedule 25.01.2012
comment
Почему бы просто не использовать реализацию кэша памяти CLR? msdn.microsoft.com/en-us/library/   -  person Kolja    schedule 25.01.2012
comment
Другой вопрос, почему бы просто не удалить хранилище MySQL Server и перейти на модель хранения, которая лучше справляется с EVA, как вы упомянули Monogo или RavenDB.   -  person Kolja    schedule 25.01.2012
comment
@Kolja - Переход на MongoDB или RavenDB - это вариант, который я рассматривал, но меня беспокоит количество времени, которое потребуется для перекодирования уровня доступа к данным. Кроме того, система используется в реальном производстве, что усложняет перемещение баз данных.   -  person philwilks    schedule 25.01.2012
comment
Тогда я бы просто подумал об использовании MemeoryCache. Это должно быть самым простым в реализации и не требует чтения/записи жесткого диска при поиске в кеше. И это забирает у вас всю обработку истечения срока действия кеша. Вы можете легко настроить объем кэш-памяти, который вы хотите использовать, чтобы найти наилучшее значение для вашего приложения.   -  person Kolja    schedule 25.01.2012
comment
@Kolja - Просто чтобы подтвердить то, что вы предлагаете, будет ли это означать, что я загружаю все свои объекты в MemeoryCache, включая все их атрибуты? Если да, то знаете ли вы, можно ли эффективно выполнять запросы к этим объектам?   -  person philwilks    schedule 25.01.2012
comment
Для меня это действительно похоже на кеширующий слой. Вы можете использовать MongODB, хотя вы также можете взглянуть на Redis (redis.io) или даже просто на Memcache/Membase, которые оба разработаны как кэши.   -  person Gates VP    schedule 25.01.2012


Ответы (1)


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

Во-первых, вы действительно можете перейти на документно-ориентированную базу данных, такую ​​​​как Mongo, - это подходит в качестве альтернативы EAV. Так как не будет JOIN и прочей логики, будет очень быстро и немного масштабируемо. (Так что, возможно, вы сможете избежать использования кеша).

Во-вторых, вы можете использовать специальный инструмент для кэширования, такой как Redis, Mongo или Memcached, чтобы сохранять каждый результат запроса в течение некоторого времени.

Но я хочу обратить наше внимание на будущее этой системы. Какая планируется загрузка и масштабирование? Если вы хотите уменьшить нагрузку на систему, я думаю, что лучший способ — перейти на документно-ориентированную базу данных. Или, если вы хотите получить результат немедленно (кешировать данные для чтения) - его можно получить с помощью инструмента кэширования, даже [если возможно] на сетевом уровне (например, nginx поддерживает memcached из коробки).

Итак, как обычно, вы должны найти баланс между разовыми и постоянными затратами.

person A Ralkov    schedule 12.04.2019