Ведение статистики просмотра видео разбивка по времени видео в базе данных


Мне нужно сохранить ряд статистических данных о просмотренных видео, и одна из них-это то, какие части видео просматриваются больше всего. Дизайн, который я придумал, состоит в том, чтобы разделить видео на 256 интервалов и сохранить число просмотров с плавающей точкой для каждого из них. Я получаю данные в виде ряда интервалов, которые пользователь наблюдал непрерывно. Проблема в том, как их хранить. Есть два решения, которые я вижу.

Строка на каждый сегмент видео

Давайте создадим таблицу базы данных вот так:

CREATE TABLE `video_heatmap` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `video_id` int(11) NOT NULL,
 `position` tinyint(3) unsigned NOT NULL,
 `views` float NOT NULL,
 PRIMARY KEY (`id`),
 UNIQUE KEY `idx_lookup` (`video_id`,`position`)
) ENGINE=MyISAM
Затем, всякий раз, когда нам нужно обработать несколько представлений, убедитесь, что есть соответствующие строки базы данных и добавьте соответствующие значения в столбец views. Я обнаружил, что это намного быстрее, если сначала позаботиться о существовании строк (SELECT COUNT(*) строк для данного видео и INSERT IGNORE, если они отсутствуют), а затем использовать ряд запросов обновления следующим образом:
UPDATE video_heatmap
SET views = views + ?
WHERE video_id = ? AND position >= ? AND position < ?
Это кажется, однако, немного раздутым. Другое решение, которое я придумал, это

Строка за видео, обновление в транзакциях

Таблица будет выглядеть примерно так:

CREATE TABLE video (
 id INT NOT NULL AUTO_INCREMENT,
 heatmap BINARY (4 * 256) NOT NULL,
 ...
) ENGINE=InnoDB

Затем, каждый раз, когда представление должно быть сохранено, это будет сделано в транзакции с последовательным снимком, в последовательности, подобной этой:

  1. Если видео не существует в базе данных, оно создается.
  2. строка извлекается, heatmap, массив поплавков, хранящихся в двоичной форме, преобразуется в форму, более удобную для обработки (в PHP).
  3. значения в массиве являются увеличивается соответствующим образом, и массив преобразуется обратно.
  4. Строка
  5. изменяется с помощью запроса UPDATE.

Пока что преимущества можно суммировать следующим образом:

Первый подход

  • хранит данные как поплавки, а не как какой-то волшебный двоичный массив.
  • не требует поддержки транзакций, поэтому не требует InnoDB, и мы используем MyISAM для всего на данный момент, так что не будет никакой необходимости смешивать механизмы хранения. (применяется только в моем конкретном случае ситуация)
  • не требует транзакции WITH CONSISTENT SNAPSHOT. Я не знаю, каковы штрафные санкции за их исполнение.
  • я уже реализовал его, и он работает. (применимо только в моей конкретной ситуации)

Второй подход

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

Итак, что же мне делать? Если бы не остальная часть нашей системы, последовательно использующая MyISAM, я бы пошел со вторым подходом, но в настоящее время я склоняюсь к первому. Но, может быть, есть какие-то причины в пользу одного подход или другой?

1 2

1 ответ:

Второй подход выглядит заманчиво на первый взгляд, но он делает запросы типа "сколько просмотров для сегмента x видео y" неспособными использовать индекс на video.heatmap. Хотя не уверен, что это реальная забота для вас. Кроме того, вам придется анализировать весь массив каждый раз, когда вам нужны данные только для одного сегмента.

Но, прежде всего, ваше второе решение является хакерским (но, тем не менее, интересным). Я бы не рекомендовал денормализировать вашу базу данных до тех пор, пока вы столкнулись с острой проблемой производительности.

Также попробуйте заполнить таблицу video_headmap Заранее с помощью wiews = 0, как только будет вставлен video (триггер может помочь).

Если пространство действительно вызывает беспокойство, удалите свой суррогатный ключ video_headmap.id и вместо него сделайте (video_id, position) первичным ключом (затем избавьтесь от лишнего ограничения UNIQUE). Но это не должно входить в уравнение. 256 x 12 байт на видео (приблизительная длина строки с 3 числовыми столбцами, хорошо добавьте некоторые для индекса) - это всего лишь дополнительные 3 КБ на видео. видео! Наконец, ничто не мешает вам переключить вашу текущую таблицу на InnoDB и использовать ее возможность блокировки на уровне строк. Пожалуйста, обратите внимание, что я не могу определить, почему views не может быть UNSIGNED INT. Я бы рекомендовал изменить этот тип.