(ASP.NET) Как бы вы создали счетчик реального времени, отслеживающий изменения в базе данных?
-
21-08-2019 - |
Вопрос
Вот в чем проблема.
На сайте, который я недавно взял на себя, отслеживаются «мили», которые вы пробежали за день.Таким образом, пользователь может войти на сайт и добавить, что пробежал 5 миль.Затем это добавляется в базу данных.
В конце дня, около часа ночи, запускается сервис, который подсчитывает все мили, пройденные всеми пользователями за день, и выводит текстовый файл в App_Data.Этот текстовый файл затем отображается во флэш-памяти на домашней странице.
Я думаю, это довольно смешно.Мне сказали, что им пришлось это сделать из-за серьезных проблем с производительностью.Они не расскажут мне, как именно они это делали раньше и в чем заключалась основная проблема с производительностью.
Итак, какой подход вы бы выбрали?Первое, что пришло мне в голову, — это веб-сервис, который получает данные посредством вызова AJAX.Возможно, каждый раз, когда добавляется новая запись «миля», срабатывает триггер и обновляет таблицу «GlobalMiles».
Буду признателен за любую информацию или советы по этому поводу.
Спасибо!
Решение
Ответить на этот вопрос немного сложно, так как мы не знаем всех ваших требований и что-то раньше не работало.Итак, вот несколько разных идей.
Во-первых, пересмотрите свои предположения.Создание статического отчета один раз в день — вполне допустимое решение, если все, что вам нужно, — это ежедневные отчеты.Зачем обращаться к базе данных несколько раз в течение дня, если все, что нужно, это снимок (например, многие программы для блогов используются для записи html-файлов при публикации блога, вместо того, чтобы каждый раз обслуживать запись из базы данных - многие до сих пор это делают) в качестве оптимизации).Добавляете ли вы функцию «реального времени»?
Я бы не стал сразу переходить на AJAX.Используйте тот же метод ввода, просто переместите отчет из статического в динамический.Делать слишком много одновременно — хороший способ похоронить себя.При изменении существующего кода я стараюсь найти области, которые я могу изменить изолированно с наименьшим влиянием на остальную часть приложения.Затем, когда у вас будет динамический отчет, вы сможете добавить AJAX (и, пожалуйста, используйте прогрессивное улучшение).
Что касается самого динамического отчета, у вас есть несколько вариантов.
Конечно, вы можете просто SELECT SUM(), но похоже, что это приведет к проблемам с производительностью, если у каждого пользователя будет большое количество записей.
Если ваша база данных поддерживает это, я бы рассмотрел возможность использования индексированное представление (иногда называемое материализованным представлением).Он должен поддерживать возможность быстрого обновления суммарных данных в реальном времени:
CREATE VIEW vw_Miles WITH SCHEMABINDING AS
SELECT SUM([Count]) AS TotalMiles,
COUNT_BIG(*) AS [EntryCount],
UserId
FROM Miles
GROUP BY UserID
GO
CREATE UNIQUE CLUSTERED INDEX ix_Miles ON vw_Miles(UserId)
Если накладные расходы на это слишком велики, решение @ jn29098 подойдет.Сверните его, используя запланированную задачу.Если для каждого пользователя много записей, вы можете добавить только разницу с момента последнего запуска задачи.
UPDATE GlobalMiles SET [TotalMiles] = [TotalMiles] +
(SELECT SUM([Count])
FROM Miles
WHERE UserId = @id
AND EntryDate > @lastTaskRun
GROUP BY UserId)
WHERE UserId = @id
Если вас не заботит сохранение отдельных записей, а только общая сумма, вы можете обновлять счетчик на лету:
UPDATE Miles SET [Count] = [Count] + @newCount WHERE UserId = @id
Вы можете использовать этот метод в сочетании с SPROC, который добавляет запись и имеет оба мира.
Наконец, ваш метод триггера тоже будет работать.Это альтернатива индексированному представлению, в котором вы самостоятельно обновляете таблицу вместо SQL, делая это автоматически.Это также похоже на предыдущий вариант, в котором вы перемещаете глобальное обновление из процедуры в триггер.
Последние три параметра усложняют обработку ситуации, когда запись удаляется, хотя, если это не особенность вашего приложения, вам, возможно, не придется об этом беспокоиться.
Теперь, когда в вашей базе данных есть материализованные данные в реальном времени, вы можете динамически генерировать отчет.Затем вы можете добавить фантазии с помощью AJAX.
Другие советы
Если у них действительно возникают проблемы с производительностью из-за большого количества обращений к базе данных, я предлагаю вам взять все входные данные и поместить их в очередь сообщений (MSMQ).Тогда у вас может быть служба на другом конце, которая принимает сообщения и выполняет массовую вставку данных.Таким образом, у вас будет меньше попаданий в БД.Затем вы также можете вывести обновление в текстовый файл.
Я бы создал сводную таблицу, которая формируется один раз в час или каждую ночь и подсчитывает общий пробег в милях.Для отдельных запросов вы можете извлечь из сводной таблицы за ночь плюс любые дополнительные зарегистрированные мили за период между последним сводным расчетом и моментом, когда пользователь просматривает страницу, чтобы получить общее количество миль для этого пользователя.
О скольких пользователях вы говорите и сколько записей в журнале в день?