Я работаю над приложением, которое включает в себя очень высокое выполнение запросов на обновление / выборку в базе данных.
У меня есть базовая таблица (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 + реляционная база данных? Существуют ли какие-либо платформы / хранилища данных, которые позволяют мне часто обновлять данные без блокировки и в то же время дают мне гибкость при выполнении запросов на выборку в различных полях объекта?
источник
Ответы:
Похоже, таблица
B
является своего рода кешем. Но такого рода кеш, который снижает производительность ..Даже если у вас есть 25 запросов в секунду, вы можете отказаться от использования таблицы
B
и рассчитать ответ для каждого запроса.В любом случае , если у вас есть 30-секундная задержка при обновлении 20 записей - это сбой в программной архитектуре (я ошибаюсь, если ваша БД рассчитывает первые 10 100 знаков ПИ для каждой записи).
Как я знаю, реляционная БД без безобразных SQL-запросов, с индексами и с менее чем 1 000 000 записей отлично подойдет практически для всех запросов.
Попробуйте отказаться от использования таблицы
B
и добавить соответствующие индексы в вашу таблицуA
(в большинстве современных баз данных есть вспомогательный инструмент). Далее: попробуйте оптимизировать структуру данных (таблицыA
) и запроса (с помощью анализатора запросов или с SQL-экспертами) для ускорения расчетов. Если вы обновите только 20 записей - наличие индексов не повлияет на производительность процесса обновления , но значительно улучшит скорость выбора .источник
Вопрос на самом деле в том, какая система вычисляет запись для вставки в B и размер данных B.
Любая база данных (например, MSSQL) должна иметь возможность обрабатывать объем вставок, о которых вы говорите, без проблем, если предположить, что объект не очень большой.
Обновления могут быть более сложной проблемой, но с правильной индексацией и блокировкой, опять же, не должно быть большой проблемой.
В 99% случаев, когда я вижу подобную проблему, это происходит из-за того, что запись B вычисляется хранимым процессом. Это помещает всю нагрузку на сервер БД
Если дело обстоит так, решение состоит в том, чтобы переместить этот код в автономный сервис, который можно вызвать через систему очередей.
Таким образом, ваше сообщение об обновлении будет запускать рабочий процесс, который будет циклически проходить через пользователей и создавать сообщение об обновлении B для каждого пользователя.
Второй рабочий процесс B получит обновление пользователя X с данными A, создаст запись B и обновит базу данных.
Это можно масштабировать, добавляя больше блоков с работниками очереди, так что вы будете иметь все больше вычислительной мощности за вычислениями, оставляя свою базу данных свободной, чтобы сконцентрироваться на обновлениях и выборках.
Вы можете дополнительно оптимизировать, отделяя выбор от обновления / вставки. иметь новую БД, которая получает все запросы на выборку, в качестве подчиненного устройства репликации на старую БД, которая получает все обновления.
источник
Если вы работаете в Amazon, я бы рассмотрел DynamoDB. Это на основе флэш-памяти. Вот ссылка на него: https://aws.amazon.com/dynamodb/ .
Какие виды СУБД вы используете? Вы можете увеличить производительность, используя UDF или вычисленное поле в представлении. Выполняете ли вы вычисления в базе данных с помощью одного запроса на обновление, или вы выбираете данные из базы данных, запускаете вычисления в другом процессе и затем загружаете их обратно?
По умолчанию Oracle настроен на использование режима моментального снимка, что означает, что строки не блокируются во время обновления, и одновременные выборки получают исходное значение. SQL Server по умолчанию настроен с пессимистическим параллелизмом, поэтому одновременный выбор будет блокироваться до завершения обновления. Некоторые версии SQL Server могут быть переведены в режим моментального снимка, однако это значительно увеличивает нагрузку на временную таблицу.
В какой среде вы работаете? Если это СУБД в экземпляре EC2 в Amazon, попробуйте поместить файлы данных БД на локальную флэш-диск. Я видел разницу в порядке перемещения файлов из EBS на локальный диск.
источник