【发布时间】:2016-08-12 08:14:16
【问题描述】:
从两个表中计算点总和的最省资源的方法是什么?总点数的计算方法是从表 points 中加分并从表 points_redeemed 中减分。
points:
CREATE TABLE IF NOT EXISTS points(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
user__id INT,
tx__id INT,
points INT
) ENGINE=MyISAM;
points_redeemed:
CREATE TABLE IF NOT EXISTS points_redeemed(
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
user__id INT,
points INT
) ENGINE=MyISAM;
(上面的两个表格都被大大简化了。)
points 在事务中填充(记录在不同的表中)。当事务值更改或作废时,points 中的相应行也会更新。
points_redeemed 在用户兑换其累积积分以获得奖励时填充。
用例:
- 向用户和管理员显示统计信息:总积分、已兑换积分和未兑换积分
- 根据用户发起的兑换请求检查未兑换的积分
我想出的选项是:
a) 触发器。
创建一个表points_sum,每个user.id 一行,并添加三个触发器:
- 插入
points - 更新
points - 插入
points_redeemed
我听说 MySQL 触发器的性能不是那么好,所以我只是不确定这是否是个好主意。
b) 查看。
创建一个计算 points.points - points_redeemed.points 的视图。不知道这是否比在运行中做更好。
c) 求和表。
创建一个表 points_sum 并在每次将 points 和 points_redeemed 插入和更新时更新它。这感觉是最不有效的方法,但话说回来,我可能错了,这可能是最好的方法。
d) 即时。 动态查询两个表中的点并计算差异。这是最简单也可能是最准确的方法,但是当表格变大时,它可能会严重堵塞管道。再说一遍,在这方面还有其他选择更好吗?
编辑:这些是当前的即时查询。
首先,来自points_redeemed 的非常直接的查询:
SELECT *
FROM points_redeemed
WHERE user__id = 1
其次,查询points表:
(
SELECT p.*,
tx.*
FROM points p
INNER JOIN tx ON p.tx__id = tx.id
WHERE p.user__id = '1'
AND p.tx_is_external IS NULL
ORDER BY p.date DESC
)
UNION
(
SELECT p.*,
tx.*
FROM points p
INNER JOIN tx_external tx ON p.tx__id = tx.id
WHERE p.user__id = '1'
AND p.tx_is_external = '1'
ORDER BY p.date DESC
)
(这里选择了几个命名列,我将其缩写为 *。在第二个查询中,每行获取大约 40 列。)
在此之后,我将遍历两个结果集并在应用层上添加/减去点。
我担心的是,当 tx 表(以及 points 表)变大时,这两个单独的查询以及第二个查询中的连接可能会“堵塞管道”。这就是为什么我试图找出一种更好的方法来在运行时节省资源。
我想得越多……交易和积分插入可能比用户查看他们当前积分状态的频率要高得多。在这种情况下,触发器可能会产生相反的效果。
我将不胜感激任何形式的见解。谢谢!
【问题讨论】:
-
不要使用 MyISAM !
-
谢谢瑞克 - 为什么不呢?
-
MyISAM 速度较慢、不安全、已弃用等。在适当的时候,还可以使用
NOT NULL和UNSIGNED以及比INT更小的数据类型。PRIMARY KEY是唯一的索引吗? (我担心你过度简化了架构。) -
points.tx__id是UNIQUE,因为每个 tx 只能有一个点行。除此之外,没有其他索引。很好的回复:UNSIGNED- 我会补充一点。回复:MyISAM,我会按照你的建议阅读,谢谢你的提醒。你对这个问题也有任何建议吗?我会很感激的! -
如果
tx__id是唯一的,它可能是PRIMARY KEY,你可以去掉代理id。
标签: mysql database-design view triggers