(ASP.NET) Как бы вы создали счетчик реального времени, отслеживающий изменения в базе данных?

StackOverflow https://stackoverflow.com/questions/1072067

Вопрос

Вот в чем проблема.

На сайте, который я недавно взял на себя, отслеживаются «мили», которые вы пробежали за день.Таким образом, пользователь может войти на сайт и добавить, что пробежал 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).Тогда у вас может быть служба на другом конце, которая принимает сообщения и выполняет массовую вставку данных.Таким образом, у вас будет меньше попаданий в БД.Затем вы также можете вывести обновление в текстовый файл.

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

О скольких пользователях вы говорите и сколько записей в журнале в день?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top