阅读 164

缓存表和汇总表(计数器表)

缓存表和汇总表(计数器表)

简述

有时提升性能最好的方法是在同一张表中保存衍生的冗余数据。然而,有时也需要创建一张完全独立的汇总表或缓存表。

缓存表和汇总表与冗余的列有异曲同工之妙,只不过实现在单独的表中。

缓存表中存储与其它的表逻辑冗余的数据,将大表中活跃的数据单独拿出来构建成一张小表,通过减少单个表的数据量来提高查询性能,即所谓的热数据分离,尤其是在大表中的某些小部分数据被频繁访问时更能体现其带来的好处。

汇总表中存储与其它的表逻辑不同的衍生数据,通过减少聚合次数来提高查询性能,同样,这些数据也经常被访问。

但两者都必须面对数据的同步问题,对于允许最终一致性的场景来说,建立缓存表或者汇总表,无疑是一个好主意,但是如果需要实时更新,那就得多花一些心思来斟酌一二了。

优缺点

  • 缓存表用来存储哪些每次获取速度比较慢(其他表中活跃)的数据的表

  • 汇总表保存你的是使用groupby语句聚合数据的表

二者的目的都是显著提高查询性能,但也会增加写查询的负担,需要额外的维护任务。

然而,写操作变慢并不是读操作变得更快所付出的唯一代价,还可能同时增加读操作和写操作的开发难度

 

实际例子

仍然以网站为例,假设需要计算之前24小时内发送的消息数。在一个很繁忙的网站不可能维护一个实时精确的计数器。作为替代方案,可以每小时生成一张汇总表。这样也许一条简单的查询就可以做到,并且比实时维护计数器要高效得多。缺点是计数器并不是100%精确。

如果必须获得过去24小时准确的消息发送数量(没有遗漏),有另外一种选择。 以每小时汇总表为基础,把前23个完整的小时的统计表中的计数全部加起来,最后再加上开始阶段和结束阶段不完整的小时内的计数。

 

不严格的计数或通过小范围查询填满间隙的严格计数都比计算message表的所有行要有效得多。这是建立汇总表的最关键原因。实时计算统计值是很昂贵的操作,因为要么需要扫描表中的大部分数据,要么查询语句只能在某些特定的索引上才能有效运行,而这类特定索引-般会对 UPDATE操作有影响,所以一般不希望创建这样的索引。计算最活跃的用户或者最常见的“标签”是这种操作的典型例子。

缓存表则相反,其对优化搜索和检索查询语句很有效。这些查询语句经常需要特殊的表和索引结构,跟普通OLTP操作用的表有些区别。

例如,可能会需要很多不同的索引组合来加速各种类型的查询。这些矛盾的需求有时需要创建一张只包含主表中部分列的缓存表。一个有用的技巧是对缓存表使用不同的存储引擎。例如,如果主表使用InnoDB,用MyISAM作为缓存表的引擎将会得到更小的索引占用空间,并且可以做全文搜索。有时甚至想把整个表导出MySQL,插人到专门的搜索系统中获得更高的搜索效率,例如Lucene或者Sphinx搜索引擎。

在使用缓存表和汇总表时,必须决定是实时维护数据还是定期重建。哪个更好依赖于应用程序,但是定期重建并不只是节省资源,也可以保持表不会有很多碎片,以及有完全顺序组织的索引(这会更加高效)。

重建汇总表和缓存表的方法

当重建汇总表和缓存表时,通常需要保证数据在操作时依然可用。这就需要通过使用“影子表”来实现,“影子表”指的是-张在真实表“背后”创建的表。当完成了建表操作后。可以通过一个原子的重命名操作切换影子表和原表。例如,如果需要重建my sumary,则可以先创建my summary _new,然后填充好数据,最后和真实表做切换:

 

 


常见应用-计数器表

  • 如果应用在表中保存计数器,则在更新计数器时可能遇到并发问题。

  • 计数器表在Web应用中很常见。可以用这种表缓存一个用户的朋友数、文件下载次数等。

  • 创建一张独立的表存储计数器通常是个好办法,这样可使计数器表小且快。使用独立的表可以帮助避免查询缓存失效

实际示例:

  假设有一个计数器表,只有一行数据,记录网站的点击次数

 


网站的每次点击都会导致对计数器进行更新


问题在于,对于任何想要更新这一行的事务来说,这条记录上都有一个全局的互斥锁(mutex)。这会使得这些事务只能串行执行。要获得更高的并发更新性能,也可以将计数器保存在多行中,每次随机选择一行进行更新。这样做需要对计数器表进行如下修改:                                                                                   

然后预先在这张表增加100行数据。现在选择一个随机的槽(slot)进行更新:

要获得统计结果,需要使用下面这样的聚合:

一个常见的需求是每隔一段时间开始一个新的计数器(例如,每天一个)。如果需要这么做,则可以简单修改一下表设计:

在这个场景中,可以不用像前面的例子那样预先生成行,而用ON DUPLICATE KEY UPDATE 代替:

如果希望减少表的行数,以避免表变得太大,可以写一个周期执行的任务,合并所有结果到0号槽,并且删除其他所有的槽


文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐