#mysql #sql
#mysql — сервер #sql #mysql
Вопрос:
Я могу периодически проверять список пользователей, которые в данный момент находятся в Сети. Я хочу превратить это во что-то полезное, например, в список записей для каждого пользователя с указанием времени входа / выхода из системы. Нет другого способа определить эту информацию, кроме проверки того, кто в данный момент находится в Сети.
После некоторых размышлений я пришел к чему-то вроде этого:
CREATE TABLE onlineActivity (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
name CHAR (32) NOT NULL,
login_time DATETIME NOT NULL,
logout_time DATETIME NOT NULL,
time SMALLINT (3) NOT NULL DEFAULT 0,
online BOOL DEFAULT NULL,
UNIQUE (name, online),
PRIMARY KEY (id)
) ENGINE = MyISAM;
Я запускаю этот запрос каждые несколько минут, чтобы добавить / обновить имена в списке действий:
INSERT INTO onlineActivity (name, login_time, logout_time, online)
SELECT name, now(), now(), true FROM onlineList ON DUPLICATE KEY UPDATE logout_time = now()
И этот запрос выполняется для каждого пользователя, который вышел из системы:
(имена определяются путем сравнения двух соседних онлайновых списков, текущего и предыдущего)
UPDATE onlineActivity SET online = NULL WHERE name = ? AND online = 1
Вопросы:
- Я беспокоюсь, что использование нулевого поля (
online
) в УНИКАЛЬНОМ индексе — плохая идея и повредит производительности. Я полагаю, что MySQL, возможно, придется выполнить полное сканирование всехonline
‘s (вместо использования индекса) для каждого имени, чтобы найти то, которое не равно NULL. Мог бы кто-нибудь уточнить, так ли это здесь? Я не смог найти никакой информации о том, как MySQL справляется с такого рода ситуациями. - Другие системы баз данных (PostgreSQL, SQLite) ведут себя иначе, чем MySQL в этом отношении?
- должен ли я вместо первого запроса выполнить два запроса для каждого имени, чтобы узнать, находится ли указанный пользователь в данный момент в Сети, и действовать соответственно этому?
- Я подумал об этом дизайне, потому что хотел свести к минимуму количество используемых запросов, является ли это ошибочной идеей само по себе?
- Эта таблица будет получать около 300 ~ 500 тысяч новых записей в день. Есть ли что-то еще, что я могу сделать, чтобы уменьшить снижение производительности?
Я хочу сохранить полную историю активности пользователя, а не одну запись.
Комментарии:
1. Почему бы не присвоить онлайн-BOOL значение по умолчанию false? Не следует ли предположить, что пользователь находится в автономном режиме, если они не были зарегистрированы как подключенные?
2. Потому что это позволит использовать только две записи в таблице для каждого пользователя (одну онлайн и одну оффлайн).
Ответ №1:
Я не уверен, почему у вас уникальное имя и онлайн, поскольку то, что вы пытаетесь сделать, это создать список онлайн-активности. Ввод уникального ключа, как вы указали, будет означать, что вы можете ввести туда имя только три раза, по одному для каждого состояния (null, true, false).
Что вы эффективно делаете, так это пытаетесь создать таблицу истории, и в этом случае, чтобы использовать ваш текущий метод заполнения таблицы, вам следует ввести уникальный ключ (name, logout_time) с нулевым временем выхода из системы, указывающим на текущего пользователя, вошедшего в систему (поскольку вам нужно только одно время выхода из системы, равное нулю).).
Что-то вроде этого:
CREATE TABLE onlineActivity (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
name CHAR (32) NOT NULL,
login_time DATETIME NOT NULL,
logout_time DATETIME NULL,
time SMALLINT (3) NOT NULL DEFAULT 0,
online BOOL not null DEFAULT false,
UNIQUE (name, logout_time),
PRIMARY KEY (id)
) ENGINE = MyISAM;
Затем запустите это по расписанию, чтобы обновить таблицу
INSERT IGNORE INTO onlineActivity (name, login_time, logout_time, online)
SELECT name, now(), null, true FROM onlineList
И это при выходе пользователя из системы
UPDATE onlineActivity SET online = false, logout_time = now() WHERE name = ? AND logout_time = null
Комментарии:
1. Я не хочу, чтобы каждый пользователь был представлен только один раз, я хочу полную историю его активности, и это то, что это делает. Для каждого пользователя существуют десятки «старых» записей и не более одной «текущей» записи.
2. Отредактировал мой ответ с учетом этого.
3. Однако с этой идеей связано несколько проблем. 1) Я не могу использовать первый запрос с
onlineList
, мне нужно определить, кто находится в Сети, но я не проверял в последний раз (фактически, кто вошел в систему), потому что в противном случае это приведет к засорению таблицы несколькими (нежелательными) записями. 2) с точки зрения производительности ничего не меняется, по-прежнему существует УНИКАЛЬНЫЙ ключ с нулевым полем 3) это не отвечает ни на один из моих вопросов: p