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

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



Зарегистрирован: 10.03.2003
Сообщ.: 13553
Карма: 405
   поощрить/наказать


СообщениеДобавлено: Вс Янв 25, 2004 8:53 am ()
   Заголовок сообщения: Универсальный алгоритм отслеживания изменений.
Ответить с цитатой

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

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

Основные свойства и достоинства:
  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 из первых двух массивов снимка.

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

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

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

Последний раз редактировалось: Дмитрий Кóтеров (Вс Янв 25, 2004 5:31 pm), всего редактировалось 1 раз
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора
Юрий Насретдинов
Модератор



Зарегистрирован: 13.03.2003
Сообщ.: 8584
Карма: 237
   поощрить/наказать

Откуда: 007 495

СообщениеДобавлено: Вс Янв 25, 2004 12:32 pm (спустя 3 часа 38 минут)
   Заголовок сообщения:
Ответить с цитатой

  1. тема считается модифицированной, если дата её создания меньше даты друксования, но дата последнего ответа больше
Из этого следует, что можно удалять все записи о просмотрах темдо последнего друксования - они все равно являются "неизмененными", как после нажатия кнопки "отметить все как прочитанное".
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора ICQ Number
Дмитрий Кóтеров
Администратор



Зарегистрирован: 10.03.2003
Сообщ.: 13553
Карма: 405
   поощрить/наказать


СообщениеДобавлено: Вс Янв 25, 2004 5:34 pm (спустя 5 часов 1 минуту)
   Заголовок сообщения:
Ответить с цитатой

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

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

Это и понятно — информация о просмотрах тоиков не должна теряться. Она нужна на всем протяжении существования пользователя.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора
Юрий Насретдинов
Модератор



Зарегистрирован: 13.03.2003
Сообщ.: 8584
Карма: 237
   поощрить/наказать

Откуда: 007 495

СообщениеДобавлено: Вс Янв 25, 2004 5:37 pm (спустя 2 минуты)
   Заголовок сообщения:
Ответить с цитатой

Дмитрий Кóтеров:
Но ! Если проводить эту оптимизацию совместно со смещением пометки друксования форума (а это можно делать, когда все темы этого являются прочтенными), то этого не произойдет. Я уже помнится это много раз говорил :)
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора ICQ Number
Дмитрий Кóтеров
Администратор



Зарегистрирован: 10.03.2003
Сообщ.: 13553
Карма: 405
   поощрить/наказать


СообщениеДобавлено: Вс Янв 25, 2004 6:21 pm (спустя 44 минуты)
   Заголовок сообщения:
Ответить с цитатой

Произойдет, еще как. Докажем от противного. Педставьте 2 топика с одинаковым временем создания и модификации. В первый пользователь заходил, во второй — нет. Теперь изменились оба одновременно. При этом первый топик должен пометиться измененным («покраснеть»), а второй — нет. Следовательно, необходимо где-то хранить информацию о различиях этих топиков, и временная метка здесь не помогает — ибо она у обоих топиков одинакова.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора
Юрий Насретдинов
Модератор



Зарегистрирован: 13.03.2003
Сообщ.: 8584
Карма: 237
   поощрить/наказать

Откуда: 007 495

СообщениеДобавлено: Вс Янв 25, 2004 6:30 pm (спустя 9 минут)
   Заголовок сообщения:
Ответить с цитатой

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

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

Надеюсь, понятно объяснил :)
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора ICQ Number
Дмитрий Кóтеров
Администратор



Зарегистрирован: 10.03.2003
Сообщ.: 13553
Карма: 405
   поощрить/наказать


СообщениеДобавлено: Вс Янв 25, 2004 7:26 pm (спустя 55 минут)
   Заголовок сообщения:
Ответить с цитатой

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

То же самое — можно сделать возможность «отписаться от топика» — например, пользователь посмотрел топик, понял, что он ему не интересен, нажал кнопку, и больше за изменениями топика не следит.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора
Юрий Насретдинов
Модератор



Зарегистрирован: 13.03.2003
Сообщ.: 8584
Карма: 237
   поощрить/наказать

Откуда: 007 495

СообщениеДобавлено: Вс Янв 25, 2004 8:16 pm (спустя 49 минут)
   Заголовок сообщения:
Ответить с цитатой

Дмитрий Кóтеров:
В любом случае можно сдвигать дату друксования форума при отсутсвии новых тем ?
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора ICQ Number
Дмитрий Кóтеров
Администратор



Зарегистрирован: 10.03.2003
Сообщ.: 13553
Карма: 405
   поощрить/наказать


СообщениеДобавлено: Вс Янв 25, 2004 8:42 pm (спустя 26 минут)
   Заголовок сообщения:
Ответить с цитатой

Можно. Но определение того, что ее можно сдвинуть, весьма ресурсоемко само по себе.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора
Юрий Насретдинов
Модератор



Зарегистрирован: 13.03.2003
Сообщ.: 8584
Карма: 237
   поощрить/наказать

Откуда: 007 495

СообщениеДобавлено: Вс Янв 25, 2004 9:53 pm (спустя 1 час 10 минут)
   Заголовок сообщения:
Ответить с цитатой

Дмитрий Кóтеров:
Не факт. Можно ограничиться предположением, что если в последних 50 темах нет ни одной непрочитанной, то вся тема является непрочитанной. В таком случае это отнюдь не ресурсоемко - нужно всего-лишь ввести еще одну переменную changed, которая будет устанавливаться в true если будет хотя бы одна новая/измененная тема...
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора ICQ Number
Дмитрий Кóтеров
Администратор



Зарегистрирован: 10.03.2003
Сообщ.: 13553
Карма: 405
   поощрить/наказать


СообщениеДобавлено: Вс Янв 25, 2004 10:00 pm (спустя 6 минут)
   Заголовок сообщения:
Ответить с цитатой

Вы сами-то поняли, что написали? (-;
Я — нет.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора
Юрий Насретдинов
Модератор



Зарегистрирован: 13.03.2003
Сообщ.: 8584
Карма: 237
   поощрить/наказать

Откуда: 007 495

СообщениеДобавлено: Вс Янв 25, 2004 10:36 pm (спустя 36 минут)
   Заголовок сообщения:
Ответить с цитатой

Дмитрий Кóтеров писал(а):
Вы сами-то поняли, что написали
Я понял что я имел ввиду.
Имеется ввиду, что если на первой странице форума нет ни одной "новой" и ни одной "изменненной" темы, то в этом форуме нет новых/изменных тем, и следовательно, можно сдвинуть отметку друксования этого форума в time(). Так понятнее ?
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора ICQ Number
Дмитрий Эсс
Участник форума



Зарегистрирован: 06.07.2003
Сообщ.: 2533
Карма: 9
   поощрить/наказать

Откуда: Таллинн, Эстония

СообщениеДобавлено: Вс Янв 25, 2004 10:54 pm (спустя 18 минут)
   Заголовок сообщения:
Ответить с цитатой

yUAC:
А что это даст?
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора
Дмитрий Кóтеров
Администратор



Зарегистрирован: 10.03.2003
Сообщ.: 13553
Карма: 405
   поощрить/наказать


СообщениеДобавлено: Пн Янв 26, 2004 2:04 am (спустя 3 часа 10 минут)
   Заголовок сообщения:
Ответить с цитатой

yUAC писал(а):
Так понятнее ?
Так понятнее. Да, это верно.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора
Дмитрий Эсс
Участник форума



Зарегистрирован: 06.07.2003
Сообщ.: 2533
Карма: 9
   поощрить/наказать

Откуда: Таллинн, Эстония

СообщениеДобавлено: Пн Янв 26, 2004 4:35 pm (спустя 14 часов 30 минут)
   Заголовок сообщения:
Ответить с цитатой

yUAC:
Извеняюсь, невнимательно читал.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение Отправить e-mail Посетить сайт автора
Показать сообщения:   
Начaть нoвую тeму   Ответить на тему Часовой пояс: GMT + 3 (Москва)
Страница 1 из 1   
Вы не можете начинать темы. Вы не можете отвечать на сообщения. Вы не можете редактировать свои сообщения. Вы не можете удалять свои сообщения. Вы не можете голосовать в опросах. Вы не можете прилагать файлы к сообщениям. Вы можете скачивать файлы.
  XML