我需要保留一些有关正在观看的视频的统计信息,其中一个是视频的哪些部分最受关注。我想出的设计是将视频分成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
然而,这看起来有点臃肿。我提出的另一个解决方案是
表格看起来像这样:
heatmap
然后,每次需要存储一个视图时,它将在具有一致快照的事务中完成,顺序如下:
UPDATE
,以二进制形式存储的浮点数组,转换为更友好的处理形式(在PHP中)。WITH CONSISTENT SNAPSHOT
查询更改。到目前为止,优势可以概括为:
那么,我该怎么办?如果不是我们系统的其余部分一直使用MyISAM,我会采用第二种方法,但目前我倾向于第一种方法。但也许有一些理由支持这种或另一种方法?
答案 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
。我建议改变这种类型。