4.6 TTL索引
在一般的应用系统中,并非所有的数据都需要永久存储。例如一些系统事件、用户消息等,这些数据随着时间的推移,其重要程度逐渐降低。更重要的是,存储这些大量的历史数据需要花费较高的成本,因此项目中通常会对过期且不再使用的数据进行老化处理。
通常的做法如下。
方案一:为每个数据记录一个时间戳,应用侧开启一个定时器,按时间戳定期删除过期的数据。
方案二:数据按日期进行分表,同一天的数据归档到同一张表,同样使用定时器删除过期的表。
对于数据老化,MongoDB提供了一种更加便捷的做法:TTL(Time To Live)索引。TTL索引需要声明在一个日期类型的字段中,假定写入的文档数据如下:
执行下面的语句创建TTL索引:
这里为systemlog集合声明了一个TTL索引,其指向createdDate字段,其中expireAfterSeconds=3600表示数据将在createdDate之后3600秒(1小时)后过期。
对集合创建TTL索引之后,MongoDB会在周期性运行的后台线程中对该集合进行检查及数据清理工作。除了数据老化功能,TTL索引具有普通索引的功能,同样可以用于加速数据的查询。
1.可变的过期时间
TTL索引在创建之后,仍然可以对过期时间进行修改。这需要使用collMod命令对索引的定义进行变更,代码如下:
另外一种情形可能也比较常见,如每个文档可能拥有各自的存活时长,即老化的策略不同。
比如,在systemlog集合中,不同的事件类型的老化周期是不一样的,对于此类场景的解决办法是可以使用一个单独的字段expiredDate,用于表示每个文档的过期时间点,那么TTL索引创建的规则为:
2.使用约束
TTL索引的确可以减少开发的工作量,而且通过数据库自动清理的方式会更加高效、可靠,但是在使用TTL索引时需要注意以下的限制:
● TTL索引只能支持单个字段,并且必须是非_id字段。
● TTL索引不能用于固定集合。
● TTL索引无法保证及时的数据老化,MongoDB会通过后台的TTL Monitor定时器来清理老化数据,典型的间隔时间是1分钟。当然如果在数据库负载过高的情况下,TTL的行为则会进一步受到影响。
● TTL索引对于数据的清理仅仅使用了remove命令,这种方式并不是很高效。因此TTL Monitor在运行期间对系统CPU、磁盘都会造成一定的压力。相比之下,按日期分表的方式操作会更加高效。