Счетчик: подсчет уникальных за период

Vinny

Guest
Falc
У меня статистика разбрасывается по таблицам... Потому и не нужны join-ы...

Большие бызы типа оракла умеют стоить планы для сложных запросов, чего муська, имхо, не делает...
 

Falc

Новичок
Vinny
>>Большие бызы типа оракла умеют стоить планы для сложных запросов, чего муська, имхо, не делает...

Во-первых у мускула оптимизатор хороший.
Во-вторых STRAIGHT_JOIN тебе зачем?
 

trigger

Guest
Что, опять будем спорить про разные СУБД? [=

В поиске поищите.

Я, как и вы, тоже много знаю про всякие СУБД, но думаю, что на этом форуме больше инфы, чем у меня в голове.
 

PartizaneN

I speak PHP
2 триггер - open.by АТЦЫ!!! Жду не дождусь новой версии статистики...

2 остальным Если есть подсчет уникальных посетителей за какой-то период, то тут одним айпишником не обойдешься (да и вообще даже если за день - статистика будет неверной...) У меня в день IP несколько раз меняется... )))

Но дело даже не в этом, а дело-то в том, что если уже делаешь крутую статистика с таким наворотом как САБЖ, то надо бы сделать и "пути по сайту", ну хотябы просмотренные страницы сайта, поисковые слова... и т.д. и т.п. А вот чтобы все это осуществить разумнее всего пихать все хиты в базу (ну или файл)... А уж там... кроном, демонами, бесами разбираться со всем этим...

еще раз.... open.by АТЦЫ!!!
 

Falc

Новичок
Итак подведу итог:
1. Мускула вполне хватает для написания самой навороченой системы статистики.

2. Если нужна подробная статистика:
уникальные посетители за произвольный период на произвальной странице сайта. То нужно хранить информацию о каждом хите. Но тогда не стоит мечтать о тысячах сайтов в вашей статистике.

3. Крупные счетчики типо хотлога не хранят информацию о каждом хите. (точнее они ее скорее всего ее хранят, но за весьма ограниченый промежуток времени).

4. Для быстрого вывода больших итоговых отчетов (посещаемость по дням и прочее) необходимо хранить сводные данные, т.к. расчитывать подобную статистику для сайта с хорошей посещамостью из таблицы с хитами в реальном времени просто не реально.
 

valyala

Новичок
Вот решение поставленной задачи:
1) таблица зарегистрированных пользователей
[sql]CREATE TABLE users (
/* идентификатор пользователя */
user_id INT UNSIGNED NOT NULL,
/* день последнего посещения */
last_visit INT UNSIGNED NOT NULL,
PRIMARY KEY (user_id)
);[/sql]
2) таблица счетчиков уникальных посещений
[sql]CREATE TABLE counters (
/* номер дня, за который считается количество уникальных посетителей */
day_num INT UNSIGNED NOT NULL,
/* номер дня, когда посетители посетили ресурс в прошлый раз. last_visit <= day_num. */
last_visit INT UNSIGNED NOT NULL,
/* количество уникальных посетителей, пришедших в день day_num, которые до этого посещали ресурс в день last_visit */
cnt INT UNSIGNED NOT NULL,
PRIMARY KEY (day_num, last_visit)
);[/sql]
3) таблица для хранения дневного лога посещений
[sql]CREATE TABLE day_log (
/* идентификатор пользователя */
user_id INT UNSIGNED NOT NULL,
/* дополнительные данные */
);[/sql]
Последовательность SQL-запросов для обработки лога посещений [day_log] за день CURRENT_DAY:
1) создаем временную таблицу, содержащую список пользователей, пришедших за день CURRENT_DAY:
[sql]CREATE TEMPORARY TABLE tmp_table
SELECT DISTINCT a.user_id AS user_id,
IF(ISNULL(b.last_visit), CURRENT_DAY, b.last_visit) AS last_visit
FROM day_log AS a LEFT JOIN users AS b ON (a.user_id = b.user_id)[/sql]
2) обновляем день последнего посещения на CURRENT_DAY для пришедших в этот день пользователей:
[sql]UPDATE users SET last_visit = CURRENT_DAY WHERE user_id IN (SELECT user_id FROM tmp_table)[/sql]
3) добавляем новых пользователей в таблицу [users] для дня CURRENT_DAY:
[sql]INSERT INTO users (user_id, last_visit)
SELECT user_id, last_visit FROM tmp_table
WHERE last_visit = CURRENT_DAY[/sql]
4) добавляем новые строки в таблицу [counters], соответствующие дню CURRENT_DAY:
[sql]INSERT INTO counters (day_num, last_visit, cnt)
SELECT CURRENT_DAY, last_visit, COUNT(user_id) FROM tmp_table
GROUP BY last_visit[/sql]
5) удаляем временную таблицу
[sql]DROP TABLE tmp_table[/sql]

А вот и те запросы, ради которых мы так трудились:
1) запрос, возвращающий количество уникальных посетителей за определенный день M:
[sql]SELECT SUM(cnt) FROM counters
WHERE day_num = M[/sql]
2) запрос, возвращающий количество уникальных посетителей за количество дней N, начиная с дня M (если N == 1, то этот запрос превращается в предыдущий):
[sql]SELECT SUM(cnt) FROM counters
WHERE day_num >= M AND day_num < M + N AND (last_visit = day_num OR last_visit < M)[/sql]
[day_num] и [last_visit] - не обязательно номера дней. Это
могут быть последовательные номера любых интервалов времени, в зависимости от дискретности, с которой надо выводить отчеты.
В итоге скорость выполнения запроса по уникальным посетителям за количество подряд идущих интервалов времени N, начиная с интервала M, не зависит от посещаемости сайта, на котором установлен счетчик. Она
зависит лишь от параметров N и M.
 

trigger

Guest
Привет, Валяла. Видно, что ты любишь проектировать. [=

Я при беглом просмотре не нашел, откуда берется current_day в четвертом запросе, ну да это ничего.

Вот тока... У тя 6000 сайтов. В таблице counter я так понял, n^2 записей, где n -- количество дней существования сайта. И через 12.5 месяца у тебя будет в ней "немногим" больше миллиарда записей. Нормально?

А потом... сюрприз... вебмастер выбирает подсчет уникальных за 2 года... База весело считает сумму полумиллионов записей...

Может быть, я не прав? В противном случае место твоей БД -- экспонат "как не надо делать".

PS: Причем я брал не максимальные условия.
 

valyala

Новичок
Я при беглом просмотре не нашел, откуда берется current_day в четвертом запросе, ну да это ничего.
current_day - это идентификатор (точнее, порядковый номер) дня, за который обрабатывается лог-таблица.
Вот тока... У тя 6000 сайтов. В таблице counter я так понял, n^2 записей, где n -- количество дней существования сайта. И через 12.5 месяца у тебя будет в ней "немногим" больше миллиарда записей. Нормально?
Ты взял самый худший случай, когда:
- все 6000 сайтов имеют высокую посещаемость
- каждый день на каждый сайт приходят хотя бы n человек, где n - количество дней, прошедших с начала сбора статистики. В том числе:
1) в первый день на каждый сайт пришло хотя бы n человек (как и во все последующие дни :) )
2) во второй - хотя бы n - 1 новых плюс хотя бы один, который пришел в первый день
3) в третий - хотя бы n - 2 новых плюс хотя бы по одному с первого и второго дня
....
n) в n-й день - хотя бы один новый юзер плюс хотя бы по одному с каждого предыдущего дня
А теперь предположи, какова вероятность такого случая?
К тому же ты не умеешь считать. В худшем случае в таблице будет не n^2, а всего лишь 1 + 2 + ... + n = n * (n + 1) / 2 записей :)
А потом... сюрприз... вебмастер выбирает подсчет уникальных за 2 года... База весело считает сумму полумиллионов записей...
Опять у тебя проблемы со счетом. В худшем случае, описанном выше, база весело считает сумму N = n * (m + 1) записей, где n - количество дней в интервале, m - день начала интервала. Если нужно подсчитать количество уникальных за два года с начала сбора статистики, то n = 730, m = 0. Значит, N = 730, а вовсе не 500000 :)
PS: Причем я брал не максимальные условия.
Ты взял как раз самый худший и нереальный случай.
 

Falc

Новичок
valyala
Хорошее решение для данной задачи. В середнем за день для одного сайта в табличку counters, будет падать порядка 100 записей. Подсчитать суму будет не долго.
 

trigger

Guest
подсчет уникальных за период

Автор оригинала: valyala
current_day - это идентификатор (точнее, порядковый номер) дня, за который обрабатывается лог-таблица.
То есть там скрипт подставляет значение, а не мускул обрабатывает эту строку, я понял.

Ты взял самый худший случай, когда:
- все 6000 сайтов имеют высокую посещаемость
Ыть! Имхо, без разницы, сколько их приходит. Есть разница, с каких дней они приходят (но в общем, ты прав [=). см ниже
- каждый день на каждый сайт приходят хотя бы n человек, где n - количество дней, прошедших с начала сбора статистики. В том числе:
1) в первый день на каждый сайт пришло хотя бы n человек (как и во все последующие дни :) )
2) во второй - хотя бы n - 1 новых плюс хотя бы один, который пришел в первый день
3) в третий - хотя бы n - 2 новых плюс хотя бы по одному с первого и второго дня
....
n) в n-й день - хотя бы один новый юзер плюс хотя бы по одному с каждого предыдущего дня
А теперь предположи, какова вероятность такого случая?
А вот здесь ты, наверно, прав. Я сразу считал что посещают довольно много людей из непостоянной аудитории сайта. Но если ресурс будет хотя бы как open.by то примерно так и будет. ( если в день посетителей больше, чем дней с начала статистики)

К тому же ты не умеешь считать. В худшем случае в таблице будет не n^2, а всего лишь 1 + 2 + ... + n = n * (n + 1) / 2 записей :)
Ого! Ты же в БГУИР учишься, а что такое асимптотические оценки не знаешь. [=
Открой скобки и получишь O(n^2), если тебе так больше нравится.
Опять у тебя проблемы со счетом. В худшем случае, описанном выше, база весело считает сумму N = n * (m + 1) записей, где n - количество дней в интервале, m - день начала интервала. Если нужно подсчитать количество уникальных за два года с начала сбора статистики, то n = 730, m = 0. Значит, N = 730, а вовсе не 500000 :)
Ну так дополни сам мой вопрос! "вебмастер выбирает подсчет уникальных за 2 года", через 2 года сбора статистики. [= А если будешь вести лог по часам, а не по дням, то ... [=

В общем, моя оценка Валялиной структуры БД: для легкой статистики пойдет. Для того, что хочет поставить нечто подобное для своего сайта -- самое то! Только не ждите от нее сложных отчетов типа путей по сайту, географии (откуда приходили юзеры), какими user_agent пользовались за определенный промежуток времени. Как сказал Valyala: "Вот решение поставленной задачи", вернее не совсем поставленной, тк минимальный период -- день.

2 Valyala: если ты напишешь еще парочку таблиц для всяких географий, будет интересно посмотреть. [=
 

Vinny

Guest
valyala
Что-то я не совсем понял... В таблице counters у нас хранится статистика уников по дням... Как мы из нее получаем уников за период? Ведь SUM(cnt) тут не прокатывает...
 

PartizaneN

I speak PHP
Извини, триггер, но ты не прав...

Всякую географию, ссылы, пути у валялы можно взять из таблицы day_log ... Подробнее про это писать нет смысла...
А минимальный период час - это вообще не задача... Одной таблицой больше, одной меньше... Если ты конечно не имеешь в виду - сколько уников пришло с 10.00 вчера по 9.00 сегодня...
И это решаемо, только надо ли???


Лично у меня -
При хите пользователя сразу пишутся данные в 2 таблицы -
1) которая пишет всю инфу, т.е. дату, идентификатор, айпишник, ссылу, .... и т.п. Т.е. что-то типа дэйлога у Валялы...
2) таблица, в которой посещаемость сайта (ну т.е. дата, ид сайта, хосты, хиты)...
2-ая нужна, чтобы на счетчике рисовать оперативные данные...

Дальше кроном данные пихаются во все остальные таблойды... Хиты по часам, ссылы...

Чтобы слишком не росла 1 таблица - каждый день она чистится...

А вот насчет опенбай... Это же самый песещаемый сайт в байнете... У следующего сайта в рейтинге посещаемость в 2 раза меньше... И не такие уже это миллиарды записей...)))
 

Falc

Новичок
PartizaneN
>>Дальше кроном данные пихаются во все остальные таблойды... Хиты по часам, ссылы...

>>Чтобы слишком не росла 1 таблица - каждый день она чистится...

А если пользователю надо знать сколько было уникальных посетителей на заданой странице в заданный промежуток времени и пришедших с определенного рефера, ты из каких данных отчет строишь?
 

PartizaneN

I speak PHP
И где ты такие извращенные отчеты видел?
Такого у меня нет... Но идея интересная... итак... Создаем таблицу.... дата, юзверь_ид, сайт_ид, Реферер, хиты... (На заданной конкретной странице - это вообще изврат, но если приперло и тебе заплатили за это деньги... Специально для этих людей - таблойд с почти полной (с только нужной) записью всех хитов... Единственное, что можно сделать - эттто отчет о том откуда и куда ИМЕННО пришел изверь.)

А если без конкретной страницы... Как только нету такого юзверь_ид, дата - пихаем в табло, изменился реферер - пихаем в табло, ничего не поменялось - update хит+1... Получается даже дополнительный отчет...
 

Vinny

Guest
PartizaneN
Такие извращенные отчеты есть на hotlog.ru, но, как оказалось, они там просто суммируют уники по дням, т.е., фактически, на[..censored..]...

Темой данного топика изначально было обсуждение возможных вариантов создания подобных отчетов с минимальными затратами...

Извращение или неизвращение - это риторика... Для голубых трахаться с женщиной - извращение...
 

Falc

Новичок
PartizaneN
>>И где ты такие извращенные отчеты видел?
У меня такие есть :)
Ничем они не извращенные, очень полезная информация например:
Пользователь разместил ссылку на свой сайт и хочет знать какая от нее отдача, сколько человек с этой ссылки зашли в новостной раздел, сколько зашло в каталог, сколько сделало заказ, сколько подтвердило заказ и т.д.

Генерить подобные отчеты проще из исходных данных (о каждом хите) нежели генерить кучу здоровых сводных таблиц, которые в сумме скорее всего превысят объем исходных данных. Но есть и проблемы например при запросе пользователем, например статистики о том куда и сколько пользователей за ходило с яндекса за последние 2 года, то подобный отчет будет генериться очень долго :(
 

PartizaneN

I speak PHP
Ты немного заблуждаешься... Зачем здесь исходные данные... В сводную таблицу будут писаться лишь хиты у которых есть реферер и этот реферер - не пользовательский сайт (ну ты понял)...


2 года - это конечно хорошо, но лучше сделать, чтобы максимальный период просмотра подобных отчетов был чуть меньше )))....
 

Falc

Новичок
PartizaneN
>>Зачем здесь исходные данные... В сводную таблицу будут писаться лишь хиты у которых есть реферер и этот реферер - не пользовательский сайт (ну ты понял)...

А если пользователь захочет по всем посетителям, а не только с конкретного рефера? А если пользоваетль хочет знать не только число посетителей, но кол-во хитов
 

PartizaneN

I speak PHP
2 vinny Нету в хотлоге даже отчета - куда пришел юзверь с конкретной ссылы...
 
Сверху