【问题标题】:MySQL trigger, view, separate table, or on-the-fly calculation for loyalty points?MySQL 触发器、视图、单独的表或忠诚度积分的即时计算?
【发布时间】: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 并在每次将 pointspoints_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 NULLUNSIGNED 以及比INT 更小的数据类型。 PRIMARY KEY 是唯一的索引吗? (我担心你过度简化了架构。)
  • points.tx__idUNIQUE,因为每个 tx 只能有一个点行。除此之外,没有其他索引。很好的回复:UNSIGNED - 我会补充一点。回复:MyISAM,我会按照你的建议阅读,谢谢你的提醒。你对这个问题也有任何建议吗?我会很感激的!
  • 如果tx__id 是唯一的,它可能是PRIMARY KEY,你可以去掉代理id

标签: mysql database-design view triggers


【解决方案1】:
  • WHERE user__id = 1 需要 INDEX(user__id) 放在桌子上。
  • ( SELECT ... ORDER BY ... ) UNION ( SELECT ... ORDER BY ... ) 不会有特定的顺序;您需要将ORDER BY 移到外面吗?
  • txtx_external 需要将 id 编入索引 (PRIMARY KEY?)
  • 你真的想要UNION DISTINCT吗?这是默认设置。 UNION ALL 更快。

解决这些问题,然后看看是否还需要讨论触发器等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-09
    • 2020-04-12
    • 2018-08-29
    • 2018-08-12
    相关资源
    最近更新 更多