Какое хранилище данных лучше всего подходит для моего сценария?

10

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

У меня есть базовая таблица (A), в которой будет около 500 записей для объекта за день. И для каждого пользователя в системе изменение этого объекта создается на основе некоторых предпочтений пользователя, и они сохраняются в другой таблице (B). Это делается cron-работой, которая выполняется каждый день в полночь.

Таким образом, если в таблице A 10 000 пользователей и 500 записей, в этот день в таблице B будет 5 миллионов записей. Я всегда храню данные за один день в этих таблицах и в полночь архивирую исторические данные в HBase. Эта настройка работает нормально, и у меня пока нет проблем с производительностью.

В последнее время в бизнес-требованиях произошли некоторые изменения, и теперь некоторые атрибуты в базовой таблице A (для 15–20 записей) будут меняться каждые 20 секунд, и на основании этого мне придется пересчитать некоторые значения для всех этих записей вариантов в таблице B для все пользователи. Несмотря на то, что меняются только 20 основных записей, мне нужно пересчитать и обновить 200 000 пользовательских записей, что займет более 20 секунд, и к тому времени произойдет следующее обновление, в результате чего все запросы Select будут поставлены в очередь. Я получаю около 3 запросов / 5 секунд от онлайн-пользователей, что приводит к 6-9 запросам на выборку. Чтобы ответить на запрос API, я всегда использую поля в таблице B.

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

Кто-нибудь здесь может предложить лучшую альтернативу? Помогает ли мне здесь nosql + реляционная база данных? Существуют ли какие-либо платформы / хранилища данных, которые позволяют мне часто обновлять данные без блокировки и в то же время дают мне гибкость при выполнении запросов на выборку в различных полях объекта?

Кувшины
источник
Вам действительно нужно хранить все эти данные? Это звучит так, как будто вам лучше рассчитать по запросу. Если вы можете рассчитать 200 тыс. Записей за чуть более 20 секунд, то будет возможно вычислить эти 20 записей * 3 пользователя = 60 записей за короткое время. Возможно, вы могли бы посмотреть, какие пользователи в какое время онлайн и оптимизировать еще больше? Похоже, вы генерируете тонны данных, которые никто никогда не использует (в то время как данные все еще действительны, по крайней мере)
thorsten müller
Генерация только для вошедших в систему пользователей - очень хороший вариант. Я тоже об этом думал, но все же это не совсем масштабируемый подход. Моя платформа будет использоваться только в дневное время и, следовательно, в это время большинство пользователей будут активны. Любые другие предложения, приятель?
Кувшины
@Jugs - Это все еще оставляет вопрос о том, можете ли вы просто рассчитать на лету. Вам нужно обновить записи, или вашему приложению нужны только данные?
Бобсон
Боюсь, я не могу рассчитать на лету, так как таблица записей B ранжируется для пользователя (от 5 звезд до 1 звезды), и после того, как эти вычисления сделаны, мы снова проводим ранжирование для пользователя. Весь процесс для пользователя занимает 500 мсек, и если я сделаю это на лету, это повлияет на наше время отклика API
Jugs
Я подумал, что если имеет смысл хранить оценки и рейтинги за пределами СУБД, они могут находиться в базе данных nosql, так что операторы select будут по-прежнему выполняться без каких-либо отклонений, однако иногда мне нужно запрашивать оценки и оценки тоже. Так что в данный момент я немного растерялся, поэтому я ищу совет от таких экспертов, как вы, ребята
Кувшины

Ответы:

1

Похоже, таблица Bявляется своего рода кешем. Но такого рода кеш, который снижает производительность ..

Даже если у вас есть 25 запросов в секунду, вы можете отказаться от использования таблицыB и рассчитать ответ для каждого запроса.

В любом случае , если у вас есть 30-секундная задержка при обновлении 20 записей - это сбой в программной архитектуре (я ошибаюсь, если ваша БД рассчитывает первые 10 100 знаков ПИ для каждой записи).

Как я знаю, реляционная БД без безобразных SQL-запросов, с индексами и с менее чем 1 000 000 записей отлично подойдет практически для всех запросов.

Попробуйте отказаться от использования таблицы Bи добавить соответствующие индексы в вашу таблицу A(в большинстве современных баз данных есть вспомогательный инструмент). Далее: попробуйте оптимизировать структуру данных (таблицы A) и запроса (с помощью анализатора запросов или с SQL-экспертами) для ускорения расчетов. Если вы обновите только 20 записей - наличие индексов не повлияет на производительность процесса обновления , но значительно улучшит скорость выбора .

maxkoryukov
источник
1

Вопрос на самом деле в том, какая система вычисляет запись для вставки в B и размер данных B.

Любая база данных (например, MSSQL) должна иметь возможность обрабатывать объем вставок, о которых вы говорите, без проблем, если предположить, что объект не очень большой.

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

В 99% случаев, когда я вижу подобную проблему, это происходит из-за того, что запись B вычисляется хранимым процессом. Это помещает всю нагрузку на сервер БД

Если дело обстоит так, решение состоит в том, чтобы переместить этот код в автономный сервис, который можно вызвать через систему очередей.

Таким образом, ваше сообщение об обновлении будет запускать рабочий процесс, который будет циклически проходить через пользователей и создавать сообщение об обновлении B для каждого пользователя.

Второй рабочий процесс B получит обновление пользователя X с данными A, создаст запись B и обновит базу данных.

Это можно масштабировать, добавляя больше блоков с работниками очереди, так что вы будете иметь все больше вычислительной мощности за вычислениями, оставляя свою базу данных свободной, чтобы сконцентрироваться на обновлениях и выборках.

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

Ewan
источник
0

Если вы работаете в Amazon, я бы рассмотрел DynamoDB. Это на основе флэш-памяти. Вот ссылка на него: https://aws.amazon.com/dynamodb/ .

Какие виды СУБД вы используете? Вы можете увеличить производительность, используя UDF или вычисленное поле в представлении. Выполняете ли вы вычисления в базе данных с помощью одного запроса на обновление, или вы выбираете данные из базы данных, запускаете вычисления в другом процессе и затем загружаете их обратно?

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

В какой среде вы работаете? Если это СУБД в экземпляре EC2 в Amazon, попробуйте поместить файлы данных БД на локальную флэш-диск. Я видел разницу в порядке перемещения файлов из EBS на локальный диск.

Роберт-Райан.
источник