Сообщение Покритикуйте решение - подсчет активаций от 07.06.2024 9:11
Изменено 07.06.2024 9:13 Pauel
Покритикуйте решение - подсчет активаций
Есть одна задача, не даёт покоя. Ниже вариант решения на sql
У меня есть вопросы
1. какие проблемы с этим решением
2. как можно иначе на sql
3. как можно иначе на no-sql (redis?)
Нужно отслеживать количество уникальных активаций некоторых ресурсов. Клиент должен видеть сколько новых уникальных активаций было с предыдущей проверки.
Каждый пользователь в среднем раз в несколько минут будет проверять счетчик, т.к. на это завязаны некоторые бонусы для него
Частота проверок активации — не могу понять, т.к. не ясно поведение юзеров, их количество и активность
Вот так считается количество активаций
Таблица activations
id
user
Результат
Компонент работает и без union, но у большинства ресурсов активации будут крайне редкими, а раз так, то cканировать всю таблицу смысла нет.
Стоит
Вот так фиксируется последнее состояние, это на тот случай, если 'добрый' юзер обнулил своё состояние, и запрашивает всё с чистого листа.
таблица recent_activations
user
last
У меня есть вопросы
1. какие проблемы с этим решением
2. как можно иначе на sql
3. как можно иначе на no-sql (redis?)
Нужно отслеживать количество уникальных активаций некоторых ресурсов. Клиент должен видеть сколько новых уникальных активаций было с предыдущей проверки.
Каждый пользователь в среднем раз в несколько минут будет проверять счетчик, т.к. на это завязаны некоторые бонусы для него
Частота проверок активации — не могу понять, т.к. не ясно поведение юзеров, их количество и активность
Вот так считается количество активаций
Таблица activations
id
user
(
SELECT id, COUNT(*) OVER() AS count
FROM activations
WHERE user = $1 AND id > $2 AND <кучка условий>
ORDER BY id DESC
LIMIT 1
)
SELECT id, count FROM aux
UNION ALL
SELECT
MAX(id) AS id,
0 AS count
FROM activations
Результат
3333 25 <- 25 активаций с последнего раза
4018 0 <- если не было активаций, следующий раз будем сканировать с 4018
Компонент работает и без union, но у большинства ресурсов активации будут крайне редкими, а раз так, то cканировать всю таблицу смысла нет.
Стоит
Вот так фиксируется последнее состояние, это на тот случай, если 'добрый' юзер обнулил своё состояние, и запрашивает всё с чистого листа.
таблица recent_activations
user
last
INSERT INTO recent_activations (user, last)
VALUES ($1, $2)
ON CONFLICT (user)
DO UPDATE SET
user = $1,
last = $2
WHERE recent_activations.last <= $2
Покритикуйте решение - подсчет активаций
Есть одна задача, не даёт покоя. Ниже вариант решения на sql
У меня есть вопросы
1. какие проблемы с этим решением
2. как можно иначе на sql
3. как можно иначе на no-sql (redis?)
Нужно отслеживать количество уникальных активаций некоторых ресурсов. Клиент должен видеть сколько новых уникальных активаций было с предыдущей проверки.
Каждый пользователь в среднем раз в несколько минут будет проверять счетчик, т.к. на это завязаны некоторые бонусы для него
Частота проверок активации — не могу понять, т.к. не ясно поведение юзеров, их количество и активность
Вот так считается количество активаций
Таблица activations
id
user
Результат
Компонент работает и без union, но у большинства ресурсов активации будут крайне редкими, а раз так, то cканировать всю таблицу смысла нет.
Стоит
Вот так фиксируется последнее состояние, это на тот случай, если 'добрый' юзер обнулил своё состояние, и запрашивает всё с чистого листа.
таблица recent_activations
user
last
PS. SQL код приблизительный, упрощенный, но функционально рабочий.
У меня есть вопросы
1. какие проблемы с этим решением
2. как можно иначе на sql
3. как можно иначе на no-sql (redis?)
Нужно отслеживать количество уникальных активаций некоторых ресурсов. Клиент должен видеть сколько новых уникальных активаций было с предыдущей проверки.
Каждый пользователь в среднем раз в несколько минут будет проверять счетчик, т.к. на это завязаны некоторые бонусы для него
Частота проверок активации — не могу понять, т.к. не ясно поведение юзеров, их количество и активность
Вот так считается количество активаций
Таблица activations
id
user
(
SELECT id, COUNT(*) OVER() AS count
FROM activations
WHERE user = $1 AND id > $2 AND <кучка условий>
ORDER BY id DESC
LIMIT 1
)
SELECT id, count FROM aux
UNION ALL
SELECT
MAX(id) AS id,
0 AS count
FROM activations
Результат
3333 25 <- 25 активаций с последнего раза
4018 0 <- если не было активаций, следующий раз будем сканировать с 4018
Компонент работает и без union, но у большинства ресурсов активации будут крайне редкими, а раз так, то cканировать всю таблицу смысла нет.
Стоит
Вот так фиксируется последнее состояние, это на тот случай, если 'добрый' юзер обнулил своё состояние, и запрашивает всё с чистого листа.
таблица recent_activations
user
last
INSERT INTO recent_activations (user, last)
VALUES ($1, $2)
ON CONFLICT (user)
DO UPDATE SET
user = $1,
last = $2
WHERE recent_activations.last <= $2
PS. SQL код приблизительный, упрощенный, но функционально рабочий.