我设计了一个应用程序来分析一个城市不同地方的客流量统计数据。
我为每个计数站点设计了一个数据表(以下简称DT
):startDate
(DATETIME),dataCount
( INT).
每条记录都包含计数的开始日期和柜台前访问的数量。每条记录都清楚访问的次数。记录间隔取决于计数器(一般为每小时数据)。
我有一张表(以下简称resumeDT
)总结了我所有的统计站点:name, dateReference
, location
, 描述
...和dailyAvg
。
我想创建一个这种类型的触发器:
CREATE TRIGGER avgDT AFTER UPDATE,INSERT,DELETE ON DT
FOR EACH ROW UPDATE resumeDT SET avg= (SELECT AVG(tmp.sum)
FROM (SELECT sum(count) FROM DT GROUP BY DATE(date)) tmp)
WHERE dateReference="DT"
让我有点烦恼的是,如果我一次插入500个值,我会额外执行500个UPDATE。我想在最后只执行一次我的更新查询。
我知道 FOR EACH ROW
在触发器的语法中是强制性的,但我能找到一种解决方法来做我想做的事吗?
也许只使用触发器来增加一个 mysql 变量 @DTChanged
并调用一个每秒扫描 @DTChanged
的外部脚本。 if (@DTChanged!= 0 and lastDTChanged==@DTChanged)
(1 秒内没有插入或更新)=> 更新 resumeDT
您有什么建议或其他解决方案吗?
预先感谢您的帮助。
最佳答案
关于触发器的问题是一个叫做 RBAR(Row By Agonizing Row)的概念。标准触发器(最常用且易于实现)通常是基于行的
https://www.sqlservercentral.com/Forums/Topic642789-338-1.aspx
我不知道 MySQL 的基于语句的触发器。但它们确实存在于其他数据库引擎(RDBMS) https://en.wikipedia.org/wiki/Database_trigger
本案例的解决方案
1) 在其他数据库上,有一个称为实体化 View 的标准功能。自动更新的可以满足您的需求。问题是,对于在表上完成的每个更新,它都会触发需要资源和时间才能完成的刷新,这将影响您的交易时间。鉴于其优化器功能,某些数据库(如 DB2)甚至能够将汇总数据用于甚至不引用汇总表的查询。
2)关于MySQL,鉴于其开放性,它可能作用于事务/二进制日志,其中记录了对数据库所做的所有更改(这也称为流处理)。将此信息的范围称为(二进制日志)更改数据捕获。下面的工具 maxwells-daemon 允许您捕获和处理到目前为止所做的更改。甚至还有另一个工具可以模拟实体化 View (flexviews)
https://mariadb.com/kb/en/library/flexviews/
请记住,二进制日志仅在事务提交后才“有效”/“有用”,因此,如果您的 CDC 确实处理了此问题,则可能会发生延迟。最好检查一下
关于mysql触发器 "without"FOR EACH ROW,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24202004/