Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: расчет времени проведенного онлайн

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (2): [1] 2 »   

> Описание: mysql php
wmaster
Отправлено: 04 Декабря, 2011 - 04:57:04
Post Id


Новичок


Покинул форум
Сообщений всего: 14
Дата рег-ции: Дек. 2011  


Помог: 0 раз(а)




Задача узнать и показать на графике (график это уже дело десятое) активность пользователя: в какое время был, в какое нет + соотношение онлайн/офлайн.

Есть скрипт который опрашивает статус пользователя каждый 5-10 минут, в сети он или нет. Если в сети - 1, нет - 0. Скрипт простой и по необходимости можно внести логику.

база состоит из таблиц с именами пользователей: u1, u2...

структура таблицы:

    `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `status` tinyint(4) NOT NULL


Проблемы:

1. Тупо собирать 1 и 0 очень накладно. На одного пользователя выходит порядка 300 строк в сутки. Поэтому можно немного хитрить. Допустим в 12:00 user1 online, пишем в БД (1), а в 15:30 ему валить пора, тогда и пишем в базу новую строку (0). Более экономично, даже если user1 будет часто туда-сюда "бегать".


2. Как высчитать, время онлайн или офлайн по каждому пользователю? Не пойму, как сложить эти интервалы Улыбка

Могу переделать все с нуля, просто не могу понять, как лучше реализовать, чтобы БД не распухла через месяц и в человеко понятном виде смотрелось Улыбка

Возможно где-то есть уже похожее, я бы поковырялся.
 
 Top
Panoptik
Отправлено: 04 Декабря, 2011 - 10:06:09
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2493
Дата рег-ции: Нояб. 2011  
Откуда: Одесса, Украина


Помог: 131 раз(а)




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


-----
Just do it
 
 Top
DlTA
Отправлено: 04 Декабря, 2011 - 10:21:21
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2952
Дата рег-ции: Окт. 2010  


Помог: 53 раз(а)




весь вопрос в дискретизации, в данном случае подойдет метод записи в базу интервалов, например, время когда зашел и сколько пробыл, главное чтоб интервалы не пересикались

в таком случае можно будет легко посчитать сколько всего пробыл
и график строить просто
 
 Top
tuareg
Отправлено: 04 Декабря, 2011 - 11:22:00
Post Id


Участник


Покинул форум
Сообщений всего: 1234
Дата рег-ции: Июнь 2010  


Помог: 69 раз(а)




Здравствуйте.
Я так вот на вскидку. Сделал бы так
1.Первая таблица с полями `time`(время HH:MM),`user`,`status` ENUM('yes','no')==>допустим STAT_DAY
2.Создать вторую таблицу и в ней уже хранить результирующие данные из первой таблицы
==>допустим STAT_Poln
Тогда логика следующая:
В 00:00 каждого дня по крону запускать скрипт или процедуру, которая будет собирать данные из первой таблицы(STAT_DAY) и заносить ее во вторую(STAT_Poln) и очищать первую.

Плюсы данного подхода простой запрос для внесения в первую таблицу, кстати можно посмотреть и сделать ее тип MEMORY.(Работают быстро, если превысят объем то будет как MyISAM (это так на вскидку))


P.S можно записывать только активных юзеров.
Пример время 12:00 активны юзеры 1,2,3 их записываем в Бд. Время 12:10 активны 1,3, а юзер 2 вышел тогда записываем 1,3
При таком подходе из таблицы STAT_DAY можно убрать поле status
На счет запросов сейчас еще подумаю Улыбка

добавление
Если делать запрос через равный интервал(5 мин), то количество времени OnLine посчитаем простым COUNT(*), который умножим на 5 минут и получим время юзера OnLine

(Отредактировано автором: 04 Декабря, 2011 - 11:40:00)

 
 Top
wmaster
Отправлено: 05 Декабря, 2011 - 19:46:44
Post Id


Новичок


Покинул форум
Сообщений всего: 14
Дата рег-ции: Дек. 2011  


Помог: 0 раз(а)




tuareg, пошел вашим путем. Сделал так.

таблица
u111: date (timestamp), duration (tinyint) // дата и время проведенное в онлайн в минутах, уже посчитаное.

u111_temp: date (timestamp), status (tinyint) // дата и статус онлай, пишем если пользователь в сети.


1. Скриптом, каждый 5 минут собираем статусы по u111 пользователям, пишем в u111_temp (12*24 = 288 записей в сутки на пользователя).
2. SQL запросом выбираем из таблицы u111_temp данные по активности, суммируем количество "онлайнов" и группируем по часам, иногда проще показать сам запрос, чем описывать как он работает:

CODE (SQL):
скопировать код в буфер обмена
  1. SELECT DATE_FORMAT(date,'%d %b %Hh') AS hours, SUM(STATUS) * 5 AS duration FROM u111_temp GROUP BY `hours`

3. В таблицу u111 переносим почасовую активность (то, что получили в прошлом запросе).
4. Очищаем таблицу u111_temp (можно раз в сутки, можно еще как-то, пока не придумал, как лучше)


Думаю, что такой способ разгрузит БД по нескольким причинам:
1. Экономия записей на каждом пользователе (24 в сутки)
2. Запись только "онлайна" во "временную" таблицу снижает количество обращений (если бы я писал еще и оффлайны)
3. Удобная структура таблицы u111, для отображения статистики.

Проблема

Можно ли сделать шаг 2 и 3 (а может и 4) одним SQL запросом? Типа так:
CODE (SQL):
скопировать код в буфер обмена
  1. INSERT INTO u111 (hours, duration) SELECT DATE_FORMAT(date,'%d %b %Hh') AS hours, (count(*) * 5) AS duration FROM u111_temp GROUP BY `hours`


В данном случае будет ошибка, потому что формат даты не совпадает, а мне бы хотелось всё и везде хранить в timestamp

Структура таблиц:
Спойлер (Отобразить)

Спойлер (Отобразить)

(Отредактировано автором: 05 Декабря, 2011 - 21:24:33)

 
 Top
tuareg
Отправлено: 06 Декабря, 2011 - 00:44:28
Post Id


Участник


Покинул форум
Сообщений всего: 1234
Дата рег-ции: Июнь 2010  


Помог: 69 раз(а)




Я рад что пошли моим путем Улыбка .
Напишите запрос как Вы сохраняете user в u111_temp? Я пока не понимаю, что за поле STATUS???
Просто в первом посте Вы указали, что надо каждого user-а, а сейчас я понимаю уже сумму всех user-ов на сайте?
Если да, то тогда вообще все еще проще можно сделать и будет у вас всего кол-во записей в таблице равное количеству интервалов.

(Отредактировано автором: 06 Декабря, 2011 - 01:08:17)

 
 Top
wmaster
Отправлено: 06 Декабря, 2011 - 01:47:12
Post Id


Новичок


Покинул форум
Сообщений всего: 14
Дата рег-ции: Дек. 2011  


Помог: 0 раз(а)




tuareg пишет:
Я рад что пошли моим путем Улыбка .
Напишите запрос как Вы сохраняете user в u111_temp? Я пока не понимаю, что за поле STATUS???
Просто в первом посте Вы указали, что надо каждого user-а, а сейчас я понимаю уже сумму всех user-ов на сайте?
Если да, то тогда вообще все еще проще можно сделать и будет у вас всего кол-во записей в таблице равное количеству интервалов.


1. Как я и писал, нужно для каждого отдельно вести статистику. (кол-во минут в день и соответственно кол-во часов в сутки, ну и тд.) Со времени первого поста я немного переделал структуру таблицы и логику скрипта, который опрашивает пользователей.

2. поле Status хранит единичку, если пользователь онлайн, если офф - то в базу ничего не пишет.

Запрос в таблицу u111_temp, допустим, пользователь на момент проверки онлайн:

CODE (SQL):
скопировать код в буфер обмена
  1. INSERT INTO `u111_temp` (date,STATUS) VALUES ($date, 1);


В общем-то я могу все действия делать тремя запросами, просто интересно, можно ли объединить запросы так как я спрашивал выше.

P.S. Теперь ищу удобное средство, чтобы графики рисовать Улыбка
 
 Top
tuareg
Отправлено: 06 Декабря, 2011 - 02:28:38
Post Id


Участник


Покинул форум
Сообщений всего: 1234
Дата рег-ции: Июнь 2010  


Помог: 69 раз(а)




Может я тогда, что-то недопонимаю. Улыбка Итак:
время 12:00 у нас 5 активных user(их id==>1,2,3,4,5)
Если нам надо по сайту сколько user---> INSERT INTO .... (время, 5) Не надо ставить 1.
Т.е всего одна запись, в которой уже все сосчитано, но тут мы не сможем вывести статистику на конкретного user
По конкретному user я предлагал INSERT ... VALUES ('12:00',1),('12:00',2),('12:00',3),('12:00',4),('12:00',5)
Поле таблицы на день зачем timestamp? Есть формат time(чч.мм.сс) более оптимально ИМХО, а в дату уже потом конвертировать при сохранении в основную таблицу.

P.S Просто я не могу понять как Вы определяете что именно я был на Вашем сайте в 12:00, а не Пупкин?
Либо у Вас еще какая-то таблица используется???
Т.е в 12:00 стоит 1 и как Вы определяет кто этот 1???
 
 Top
wmaster
Отправлено: 06 Декабря, 2011 - 12:24:50
Post Id


Новичок


Покинул форум
Сообщений всего: 14
Дата рег-ции: Дек. 2011  


Помог: 0 раз(а)




tuareg пишет:
Может я тогда, что-то недопонимаю. Улыбка Итак:
время 12:00 у нас 5 активных user(их id==>1,2,3,4,5)
Если нам надо по сайту сколько user---> INSERT INTO .... (время, 5) Не надо ставить 1.
Т.е всего одна запись, в которой уже все сосчитано, но тут мы не сможем вывести статистику на конкретного user
По конкретному user я предлагал INSERT ... VALUES ('12:00',1),('12:00',2),('12:00',3),('12:00',4),('12:00',5)
Поле таблицы на день зачем timestamp? Есть формат time(чч.мм.сс) более оптимально ИМХО, а в дату уже потом конвертировать при сохранении в основную таблицу.

P.S Просто я не могу понять как Вы определяете что именно я был на Вашем сайте в 12:00, а не Пупкин?
Либо у Вас еще какая-то таблица используется???
Т.е в 12:00 стоит 1 и как Вы определяет кто этот 1???


я наверное вас запутал еще в первых постах Улыбка

Суть в том, что таблицы u111 и u111_temp - таблицы пользователя 111, для 222 будет соответственно u222 и u222_temp

Скрипт опрашивает онлайн статусы моих друзей Вконтакте, через API. Да не суть, даже простых посетителей форума можно "считать" так же, по нику, например.
 
 Top
wmaster
Отправлено: 06 Декабря, 2011 - 16:25:09
Post Id


Новичок


Покинул форум
Сообщений всего: 14
Дата рег-ции: Дек. 2011  


Помог: 0 раз(а)




Я кажется нашел то, что хотел. Одним запросом я делаю выборку по временной таблице u$UID_temp, и посчитанные значения уже пишу в u$UID

CODE (SQL):
скопировать код в буфер обмена
  1. INSERT INTO $tbl (date, duration) SELECT DATE_FORMAT(date,'%Y-%m-%d %H') AS hours, SUM(STATUS) * 5 AS duration FROM $tbl_temp WHERE date BETWEEN '$start' AND '$end' GROUP BY `hours`
 
 Top
tuareg
Отправлено: 06 Декабря, 2011 - 19:43:44
Post Id


Участник


Покинул форум
Сообщений всего: 1234
Дата рег-ции: Июнь 2010  


Помог: 69 раз(а)




Это какой-то не хороший путь ... Если User будет 300 и > ???
Надо делать одну таблицу с временем а уже потом оттуда все дергать. Пока не поздно откажитесь от Вашего варианта Улыбка

Да и еще если идти таким путем, то можно просто записывать время без статуса зачем он нужен???
Но не то это все

(Отредактировано автором: 06 Декабря, 2011 - 19:49:04)

 
 Top
wmaster
Отправлено: 06 Декабря, 2011 - 21:50:02
Post Id


Новичок


Покинул форум
Сообщений всего: 14
Дата рег-ции: Дек. 2011  


Помог: 0 раз(а)




Возможно вы правы, только у меня пользователей не больше 100 и потом, более эффективного решения я пока не вижу.
 
 Top
tuareg
Отправлено: 06 Декабря, 2011 - 22:29:26
Post Id


Участник


Покинул форум
Сообщений всего: 1234
Дата рег-ции: Июнь 2010  


Помог: 69 раз(а)




Я же Вам его обрисовал(решение)??? Делайте одну таблицу на сутки, в нее записывайте время и id пользователя. А потом уже выбирайте из нее все что надо.
Я не вижу какие могут быть проблемы
 
 Top
wmaster
Отправлено: 06 Декабря, 2011 - 23:45:47
Post Id


Новичок


Покинул форум
Сообщений всего: 14
Дата рег-ции: Дек. 2011  


Помог: 0 раз(а)




tuareg пишет:
Здравствуйте.
Я так вот на вскидку. Сделал бы так
1.Первая таблица с полями `time`(время HH:MM),`user`,`status` ENUM('yes','no')==>допустим STAT_DAY
2.Создать вторую таблицу и в ней уже хранить результирующие данные из первой таблицы
==>допустим STAT_Poln
Тогда логика следующая:
В 00:00 каждого дня по крону запускать скрипт или процедуру, которая будет собирать данные из первой таблицы(STAT_DAY) и заносить ее во вторую(STAT_Poln) и очищать первую.

Плюсы данного подхода простой запрос для внесения в первую таблицу, кстати можно посмотреть и сделать ее тип MEMORY.(Работают быстро, если превысят объем то будет как MyISAM (это так на вскидку))


P.S можно записывать только активных юзеров.
Пример время 12:00 активны юзеры 1,2,3 их записываем в Бд. Время 12:10 активны 1,3, а юзер 2 вышел тогда записываем 1,3
При таком подходе из таблицы STAT_DAY можно убрать поле status
На счет запросов сейчас еще подумаю Улыбка

добавление
Если делать запрос через равный интервал(5 мин), то количество времени OnLine посчитаем простым COUNT(*), который умножим на 5 минут и получим время юзера OnLine


Башка уже не варит) Какая структура тогда будет у результирующей таблицы?
user, time, duration

а во временную я пишу что-то типа

time user
0:00 111
1:00 111,222
2:00 111,222
3:00 111,222,333
4:00 111
5:00 111
6:00 вообще пропустить
7:00 222
8:00 222
9:00 111,222

так?

как тогда правильно выбрать нужных мне пользователей, чтобы в результирующую писать?
 
 Top
tuareg
Отправлено: 07 Декабря, 2011 - 00:07:40
Post Id


Участник


Покинул форум
Сообщений всего: 1234
Дата рег-ции: Июнь 2010  


Помог: 69 раз(а)




Здравствуйте.
Структура следующая:
time user
0:00 111
1:00 111
1:00 222
2:00 111
2:00 222
3:00 111
3:00 222
3:00 333
Вот так. тогда запрос по пользователям:
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. SELECT COUNT(*)*5 AS duration FROM `temp_table` GROUP BY `user`
  3.  

То что записей получится много (1200 при 100 активных круглосуточно не страшно, главное очищайте ее каждый день)
Да и еще смотрите если Вы будете делать SELECT всей таблицы типа
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. INSERT INTO $tbl (date, duration) SELECT DATE_FORMAT(date,'%Y-%m-%d %H') AS hours ...
  3.  

Тогда индексы вообще не нужны.
P.S Меня мучает такой вопрос уже 2 дня мучает Улыбка А как Вы график строить будете???
Ось ox-->время, а oy-->???

(Отредактировано автором: 07 Декабря, 2011 - 00:08:30)

 
 Top
Страниц (2): [1] 2 »
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« SQL и Архитектура БД »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB