Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

Универсальный алгоритм отслеживания изменений. (Дмитрий Кóтеров)
Author Message
Дмитрий Кóтеров
Администратор



Joined: 10 Mar 2003
Posts: 13556
Карма: 403
   поощрить/наказать


PostPosted: Sun Jan 25, 2004 8:53 am ()
   Post subject: Универсальный алгоритм отслеживания изменений.
Reply with quote

Уже в который раз мне приходит в голову идея практически во сне, я включаю компьютер и записываю ее, чтобы не забыть. Хочу заметить, что на данном форуме применяется не этот алгоритм, а его давний-давний медленный, кривой (по последним сведениям) глючный. Перепишу «в виду паттерна (-;», как только руки дойдут.

Итак, алгоритм: отслеживание изменений по четырем градациям (не-просмотрена-не-интересна, просмотрена-не-изменена, просмотрена-изменена, не-просмотрена-и-новая) в большом (размер не ограничен) массиве однотипных элементов (записей в БД, например, или топиков в форуме).

Основные свойства и достоинства:
  1. малый размер для хранения промежуточных данных (в большинстве случаев умещается в куки)
  2. необязательность использования СУБД, если число измененных-записей невелико (алгоритм без JOIN)
  3. возможность работы в форумах без регистрации пользователей
  4. исключительно быстрый поиск
  5. простота алгоритма
  6. возможность «пропуска» топика, взглянув на одно его название, чтобы дальнейшем не отслеживать его изменение
Предметная область:
  1. Таблица топиков — таблица очень большого размера, хранящего записи, для которых производится отслеживание.
  2. Снимок — структура, состоящая из трех целочисленных массивов, в которых хранятся ID:
    1. массив неизменных топиков (топики, посещенные пользователем, но не изменившиеся с тех пор
    2. массив измененных топиков (топики, которые изменились с момента последнего прочтения)
    3. массив новых топиков (топики, созданные после последнего посещения)
    а также одного числа — временной метки актуальности.
Снимок назовем актуальным, если на тот момент, который соответствует его временной метке, данные о топике в нем отражают реальное положение дел в форуме. Например, снимок актуален сразу же после его построения или через 10 дней, если за это время ничего не изменилось.

Синхрониазация (актуализация) снимка — это процесс его модицикации, в результате которого неактуальный снимок становится актуальным. При синхронизации снимка также обновляется его временная метка — она устанавливается равным текущему времени. Например, начальное построение списка — актуализация. Добавление в скипок ID нового топика, если тот был добавлен кем-то с момента последней актуализации снимка — тоже актуализация.

Каждый пользователь имеет ассоциированный с ним снимок. Если снимок невелик (содержит около 5000 записей), он хранится в куках в запакованном виде (можно использовать GZip). Если же список велик, можно использовать таблицу в БД (но для этого обязательно нужна регистрация пользователя).

Ясно, что, имея снимок, мы можем легко дать ответ на поставленную задачу — вывести все измененные и новые топики.

Суть алгоритма — в оптимальной синхронизации снимка. Делается это при каждом открытии любой страницы на форуме. Производятся следующие действия:
  1. Запрашиваем все топики, время создания которых превышает время последней синхронизации. Добавляем их ID с список новых.
  2. Запрашиваем все топики, время изменения которых превышает время последней синхронизации, но время создания меньше времени синхронизации. Для каждого ID в цикле:
    1. В случае, если ID присутствует в списке неизменных топиков, переносим его в список измененных.
    2. А если ID не было в списке неизменных, ничего не делаем.
  3. Если текущая страница — страница просмотра топика с ID=id, удаляем id из списков измененных и новых топиков и добавляем — в список неизменных.
Т.к. за несколько дней, которые проходят между синхронизациями, число измененных топиков сравнительно невелико, то все эти процессы работают быстро.

Реализация возможности "пометки всех топиков прочитанными" (друксование) несколько усложняет алгоритм. Добавим к снимку еще одно поле — момент врмени друксования.

Заметим, что массив новых топиков можно не хранить в снимке, а строить каждый раз динамически. Это происходит потому, что:
  1. новый топик — это топик, созданный после последнего друксования
  2. новый топик — это топик, отсутствующий в списке измененных
  3. новый топик — это топик, отсутствующий в списке неизменных
Таким образом, получить все новые топики можно при помощи одного-единственного SQL-запроса, в части NOT IN (...) которого перечислить все ID из первых двух массивов снимка.

При друксовании необходимо лишь установить время метки друксования равным текущему. Кроме того, при показе измененных топиков следует проверять, не меньше ли дата изменения даты друксования. Если меньше, топик считается неизменным и удаляется из списка измененных (но не добавляется в список неизменных!).

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

Реализация разбтия топиков на группы-форумы тривиальна и достигается путем хранения нескольких меток друксования в снимке.

Last edited by Дмитрий Кóтеров on Sun Jan 25, 2004 5:31 pm; edited 1 time in total
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8636
Карма: 223
   поощрить/наказать

Location: 007 495

PostPosted: Sun Jan 25, 2004 12:32 pm (спустя 3 часа 38 минут)
   Post subject:
Reply with quote

  1. тема считается модифицированной, если дата её создания меньше даты друксования, но дата последнего ответа больше
Из этого следует, что можно удалять все записи о просмотрах темдо последнего друксования - они все равно являются "неизмененными", как после нажатия кнопки "отметить все как прочитанное".
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Дмитрий Кóтеров
Администратор



Joined: 10 Mar 2003
Posts: 13556
Карма: 403
   поощрить/наказать


PostPosted: Sun Jan 25, 2004 5:34 pm (спустя 5 часов 1 минуту)
   Post subject:
Reply with quote

Поправил чуть-чуть алгоритм (ошибся я там выше немного).

yUAC:
Нельзя. Тогда они при следующем изменении либо вообще не проявятся (в нынешнем варианте), либо проявятся как новые. А должны появиться как измененные.

Это и понятно — информация о просмотрах тоиков не должна теряться. Она нужна на всем протяжении существования пользователя.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8636
Карма: 223
   поощрить/наказать

Location: 007 495

PostPosted: Sun Jan 25, 2004 5:37 pm (спустя 2 минуты)
   Post subject:
Reply with quote

Дмитрий Кóтеров:
Но ! Если проводить эту оптимизацию совместно со смещением пометки друксования форума (а это можно делать, когда все темы этого являются прочтенными), то этого не произойдет. Я уже помнится это много раз говорил :)
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Дмитрий Кóтеров
Администратор



Joined: 10 Mar 2003
Posts: 13556
Карма: 403
   поощрить/наказать


PostPosted: Sun Jan 25, 2004 6:21 pm (спустя 44 минуты)
   Post subject:
Reply with quote

Произойдет, еще как. Докажем от противного. Педставьте 2 топика с одинаковым временем создания и модификации. В первый пользователь заходил, во второй — нет. Теперь изменились оба одновременно. При этом первый топик должен пометиться измененным («покраснеть»), а второй — нет. Следовательно, необходимо где-то хранить информацию о различиях этих топиков, и временная метка здесь не помогает — ибо она у обоих топиков одинакова.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8636
Карма: 223
   поощрить/наказать

Location: 007 495

PostPosted: Sun Jan 25, 2004 6:30 pm (спустя 9 минут)
   Post subject:
Reply with quote

Дмитрий Кóтеров:
В том-то и дело, что покраснеть они должны оба, а не только первая. В Вашей системе получается, что слежение идет только за теми топиками, которые пользователь уже посещал, а те, которые пользователь не посещал, либо будут светиться как новые (если дата_создания>дата_друкса), либо не будут подсвечиваться вообще (дата_создания<дата_друкса && дата_последнего_ответа>дата_друкса), но ведь это неправильно - логичнее было бы предположить, что в этой теме есть сообщения, которые он не видел, и => тема тоже является модифицированной.

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

Надеюсь, понятно объяснил :)
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Дмитрий Кóтеров
Администратор



Joined: 10 Mar 2003
Posts: 13556
Карма: 403
   поощрить/наказать


PostPosted: Sun Jan 25, 2004 7:26 pm (спустя 55 минут)
   Post subject:
Reply with quote

yUAC wrote:
идет только за теми топиками, которые пользователь уже посещал
Именно так, и никак иначе. Это единственно логичный способ. Если пользователь ни разу не видел топика, ему все равно, что там изменилось. Например, Вы ни разу не видели типичную семью аборигена Австралии, а потому Вам все равно, что у них вчера родился двенадцатый ребенок.

То же самое — можно сделать возможность «отписаться от топика» — например, пользователь посмотрел топик, понял, что он ему не интересен, нажал кнопку, и больше за изменениями топика не следит.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8636
Карма: 223
   поощрить/наказать

Location: 007 495

PostPosted: Sun Jan 25, 2004 8:16 pm (спустя 49 минут)
   Post subject:
Reply with quote

Дмитрий Кóтеров:
В любом случае можно сдвигать дату друксования форума при отсутсвии новых тем ?
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Дмитрий Кóтеров
Администратор



Joined: 10 Mar 2003
Posts: 13556
Карма: 403
   поощрить/наказать


PostPosted: Sun Jan 25, 2004 8:42 pm (спустя 26 минут)
   Post subject:
Reply with quote

Можно. Но определение того, что ее можно сдвинуть, весьма ресурсоемко само по себе.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8636
Карма: 223
   поощрить/наказать

Location: 007 495

PostPosted: Sun Jan 25, 2004 9:53 pm (спустя 1 час 10 минут)
   Post subject:
Reply with quote

Дмитрий Кóтеров:
Не факт. Можно ограничиться предположением, что если в последних 50 темах нет ни одной непрочитанной, то вся тема является непрочитанной. В таком случае это отнюдь не ресурсоемко - нужно всего-лишь ввести еще одну переменную changed, которая будет устанавливаться в true если будет хотя бы одна новая/измененная тема...
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Дмитрий Кóтеров
Администратор



Joined: 10 Mar 2003
Posts: 13556
Карма: 403
   поощрить/наказать


PostPosted: Sun Jan 25, 2004 10:00 pm (спустя 6 минут)
   Post subject:
Reply with quote

Вы сами-то поняли, что написали? (-;
Я — нет.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8636
Карма: 223
   поощрить/наказать

Location: 007 495

PostPosted: Sun Jan 25, 2004 10:36 pm (спустя 36 минут)
   Post subject:
Reply with quote

Дмитрий Кóтеров wrote:
Вы сами-то поняли, что написали
Я понял что я имел ввиду.
Имеется ввиду, что если на первой странице форума нет ни одной "новой" и ни одной "изменненной" темы, то в этом форуме нет новых/изменных тем, и следовательно, можно сдвинуть отметку друксования этого форума в time(). Так понятнее ?
Back to top
View user's profile Send private message Send e-mail Visit poster's website ICQ Number
Дмитрий Эсс
Участник форума



Joined: 06 Jul 2003
Posts: 2533
Карма: 9
   поощрить/наказать

Location: Таллинн, Эстония

PostPosted: Sun Jan 25, 2004 10:54 pm (спустя 18 минут)
   Post subject:
Reply with quote

yUAC:
А что это даст?
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Дмитрий Кóтеров
Администратор



Joined: 10 Mar 2003
Posts: 13556
Карма: 403
   поощрить/наказать


PostPosted: Mon Jan 26, 2004 2:04 am (спустя 3 часа 10 минут)
   Post subject:
Reply with quote

yUAC wrote:
Так понятнее ?
Так понятнее. Да, это верно.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Дмитрий Эсс
Участник форума



Joined: 06 Jul 2003
Posts: 2533
Карма: 9
   поощрить/наказать

Location: Таллинн, Эстония

PostPosted: Mon Jan 26, 2004 4:35 pm (спустя 14 часов 30 минут)
   Post subject:
Reply with quote

yUAC:
Извеняюсь, невнимательно читал.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic All times are GMT + 3 Hours
Page 1 of 1   
You cannot post new topics in this forum. You cannot reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
  XML