我正在开发一个项目,我需要根据性能原因创建和维护汇总表。我认为正确的术语是物化视图。
我有两个主要原因:
非规范化
我尽可能地对表格进行了规范化。因此,有些情况下我必须加入许多表来提取数据。我们使用MySQL Cluster,它在JOIN的性能方面表现相当差。
所以我需要创建可以运行更快的SELECT的非规范化表。
汇总数据
例如,我有一个包含几百万条记录的交易表。交易来自不同的网站。应用程序需要生成报告,以显示每日或每月的交易计数以及每个网站的总收入金额。我不希望报告脚本每次都计算这个,所以我需要生成一个按[site,date]划分的摘要表。
这只是一个简单的例子。我需要生成和维护许多不同类型的汇总表。
过去我通过编写几个cron脚本来完成这些工作,以保持每个摘要表的更新。但在这个新项目中,我希望能够实现更优雅,更合适的解决方案。
我更喜欢基于PHP的解决方案,因为我不是服务器管理员,当我可以通过应用程序代码控制所有内容时,我感觉最舒服。
我考虑过的解决方案:
复制VIEW的
如果结果表可以表示为单个SELECT查询,我可以生成一个VIEW。由于它们很慢,因此可以有一个cronjob将此VIEW复制到一个真实的表中。
然而,其中一些SELECT查询可能非常慢,即使对于cronjobs也是如此。如果旧行甚至没有更新,那么重新创建整个摘要数据效率不高。
每个摘要表的自定义Cronjobs
这是我之前使用的解决方案,但现在我尽量避免使用它。如果有许多汇总表,维护起来可能很麻烦。
MySQL触发器
可以向主表添加触发器,以便每次有INSERT,UPDATE或DELETE时,汇总表都会相应地更新。
没有cronjobs,摘要将是实时的。但是,如果需要从头开始重建汇总表,则必须使用另一个解决方案(可能是上面的#1)。
使用ORM挂钩/触发器
我使用Doctrine作为我的ORM。有一种方法可以添加将在INSERT / UPDATE / DELETE上触发内容的事件侦听器,而后者又可以更新汇总表。从某种意义上说,这个解决方案类似于上面的#3,但我会更好地控制这些触发器,因为它们将在PHP中实现。
实施注意事项:
完成重建
我希望避免重建摘要表,以提高效率,并且只更新新数据。但是如果出现问题,我需要能够使用主表上的现有数据从头开始重建汇总表。
忽略旧数据的更新/删除
某些摘要可以假设旧记录永远不会被更新或删除,但只会插入新记录。通过假设它不需要检查旧数据的更新,摘要过程可以节省大量工作。
但当然这并不适用于所有表格。
保持记录
假设我无法访问或不想使用二进制MySQL日志。
为了汇总新数据,摘要过程只需要记住它汇总的最后记录的最后一个主键ID。下次运行时,它可以汇总该ID之后的所有内容。但是,为了跟踪已更新/删除的旧记录,它需要另一个日志,以便它可以返回并重新汇总该数据。
我很感激任何可以提供帮助的策略,建议或链接。谢谢!
答案 0 :(得分:3)
Flexviews(http://flexvie.ws)是一个基于PHP / MySQL的开源项目。 Flexviews将增量可刷新的物化视图(如Oracle中的物化视图)添加到MySQL,使用PHP和存储过程。
它包括FlexCDC,一个基于PHP的更改数据捕获实用程序,用于读取二进制日志,以及Flexviews MySQL存储过程,用于定义和维护视图。
Flexviews支持连接(仅限内连接)和聚合,因此可用于创建汇总表。此外,您可以将Flexviews与Mondrian(一个ROLAP服务器)聚合设计器结合使用,以创建ROLAP工具可以自动使用的汇总表。
如果您无法访问日志(它可以远程读取它们,顺便说一句,因此您不需要服务器访问,但您确实需要SUPER privs),那么您可以使用Flexviews进行“COMPLETE”刷新。这会在新表名下自动创建一个“CREATE TABLE ... AS SELECT”的新表。然后使用RENAME TABLE将新表换成一个,用_old后缀重命名旧表。最后,它丢掉旧桌子。这里的优点是创建视图的SQL存储在数据库(flexviews.mview)中,并且可以通过简单的API调用进行刷新,从而自动进行交换过程。
答案 1 :(得分:2)
如上所述,Oracle中的物化视图与SQL Server中的索引视图不同。它们非常酷且有用。有关详细信息,请参阅http://download.oracle.com/docs/cd/B10500_01/server.920/a96567/repmview.htm
然而,MySql并不支持这些。
你多次提到的一件事是表现不佳。您是否检查过数据库设计以获取正确的索引,并对查询运行解释计划以查看它们为何变慢。见http://dev.mysql.com/doc/refman/5.1/en/using-explain.html。这当然是假设你的服务器调整正确,你有mysql设置和调整,例如,缓冲区缓存等等。
直接问题。你听起来像你想做的是我们经常在数据仓库中做的事情。我们有一个生产数据库和一个DW,它可以提取各种信息,汇总和预先计算,以加快查询速度。这对你来说可能有点过头了,但你可以决定。根据您为报告定义的延迟,即您需要它们的频率,我们通常会定期(每天,每周等)进行ETL(提取转换加载)过程,以从生产系统中填充DW。这对生产系统的影响很小,并将所有报告移动到另一组服务器,这也减轻了负载。在DW方面,我通常会设计不同的模式,即使用星型模式。 (http://www.orafaq.com/node/2286)星型模式包含事实表(您要测量的内容)和维度(您希望按时间,地理位置,产品类别等汇总度量的内容) SQL Server还包括一个名为SQL Server Analysis服务(SSAS)的额外引擎,用于查看事实表和维度,预先计算和构建OLAP数据立方体。在这些数据立方体中,您可以深入查看所有类型的模式,执行数据分析和数据挖掘.Oracle做的事情略有不同,但结果是一样的。
您是否想要走这条路线真的取决于业务需求以及您从数据分析中获得多少价值。正如我所说,如果你只有一些汇总表可能会有些过分,但是当你思考问题时,你可能会发现一些有用的概念。如果您的企业正在寻求商业智能解决方案,那么需要考虑这一点。
PS如果这是业务需要,您实际上可以使用名为ROLAP的东西将DW设置为“实时”工作。 Microstrategy有一个很好的产品,适用于此。
PPS你也可能想看看MS的PowerPivot(http://www.powerpivot.com/learn.aspx)我只玩过它所以我不能告诉你它是如何在非常大的数据集上运行的。