保持视频观看统计数据按数据库中的视频时间细分

时间:2013-06-24 15:57:12

标签: mysql database-design innodb myisam database-engine

我需要保留一些有关正在观看的视频的统计信息,其中一个是视频的哪些部分最受关注。我想出的设计是将视频分成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 IGNOREUPDATE 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
然而,这看起来有点臃肿。我提出的另一个解决方案是

每个视频行,事务更新

表格看起来像这样:

heatmap

然后,每次需要存储一个视图时,它将在具有一致快照的事务中完成,顺序如下:

  1. 如果视频在数据库中不存在,则会创建该视频。
  2. 检索一行,UPDATE,以二进制形式存储的浮点数组,转换为更友好的处理形式(在PHP中)。
  3. 适当增加数组中的值,然后转换回数组。
  4. 行通过WITH CONSISTENT SNAPSHOT查询更改。
  5. 到目前为止,优势可以概括为:

    第一种方法

    • 将数据存储为浮点数,而不是某些神奇的二进制数组。
    • 不需要事务支持,因此不需要InnoDB,而且我们目前正在使用MyISAM,所以不需要混合存储引擎。 (仅适用于我的具体情况)
    • 不需要交易{{1}}。我不知道那些性能损失是什么。
    • 我已经实现了它并且它有效。 (仅适用于我的具体情况)

    第二种方法

    • 使用的存储空间要少得多(第一种方法是将视频ID存储256次,并为视频的每个段存储位置,更不用说主键了。)
    • 应该更好地扩展,因为InnoDB的每行锁定而不是MyISAM的表锁定。
    • 通常可以更快地完成工作,因为要求的请求要少得多。
    • 在代码中更容易实现(虽然另一个已经实现)

    那么,我该怎么办?如果不是我们系统的其余部分一直使用MyISAM,我会采用第二种方法,但目前我倾向于第一种方法。但也许有一些理由支持这种或另一种方法?

1 个答案:

答案 0 :(得分:1)

第二种方法看起来很有诱惑力,但它会使得“视频 x 的段 x 有多少视图”无法在{{1上使用索引}}。不过,不确定这是否真的令你担忧。此外,每次只需要一个段的数据时,您就必须来回解析整个数组。

但首先,你的第二个解决方案是hackish(但仍然很有趣)。我不建议在您面临实际性能问题之前对数据库进行非规范化。

此外,只要插入video.heatmap(触发器可以提供帮助),请尝试使用video_headmap预先填充wiews = 0表。

如果确实存在空间问题,请删除您的代理键video,然后将video_headmap.id作为主键(然后摆脱多余的(video_id, position)约束)。但这不应该进入等式。每个视频256 x 12字节(粗略的行长度,3个数字列,可以为索引添加一些)每个视频只需额外3kb!

最后,没有什么可以阻止您将当前表切换到InnoDB并利用其行级锁定功能。

请注意我未能理解为什么UNIQUE不能成为views。我建议改变这种类型。