我正在创建一个带点数的小游戏,所以我有一个架构:
create table points ( id int, points int, reason varchar(10) )
并获得用户拥有的积分数是微不足道的:
select sum(points) as total from points where id = ?
然而,随着积分表的扩展,性能变得越来越重要.我想做的事情如下:
create table pointtotal ( id int, totalpoints int )
保持同步的最佳做法是什么?我是否尝试在每次更改时更新pointtotal?我是否每天都运行脚本?
(假设我有正确的钥匙 - 他们因为简洁而被排除在外)
编辑:
以下是我遗漏但应该有用的一些特征:
对点的插入/更新并不是那么频繁有大量的条目,并且有大量的请求 - 密钥非常简单,如您所见.
的最佳实践是使用规范化的数据库架构.然后DBMS使其保持最新,因此您不必这样做.
但我理解使非规范化设计具有吸引力的权衡.在这种情况下,最佳做法是更新每次更改的总数.调查触发器.这种做法的优点是,您可以使总数与变化保持同步,这样您就不必考虑它是否已过时.如果提交了一个更改,则也会提交更新的总计.
但是,这在并发更改方面存在一些缺点.如果您需要适应同一总计的并发更改,并且您可以容忍总计"最终一致",则使用定期重新计算总计,因此您可以确保一次只有一个流程正在更改总计.
另一个好的做法是在数据库外部缓存聚合总计,例如memcached或应用程序变量,这样您就不必在每次需要显示值时都访问数据库.
查询" select sum(points) as total from points where id = ?
"应该不会需要2秒,即使你有行数量庞大和大量的请求.
如果您定义了覆盖索引,(id, points)
则查询可以生成结果而无需从表中读取数据; 它可以通过读取索引本身的值来计算总数.使用EXPLAIN分析查询并在Extra列中查找"Using index"注释.
CREATE TABLE Points ( id INT, points INT, reason VARCHAR(10), KEY id (id,points) ); EXPLAIN SELECT SUM(points) AS total FROM Points WHERE id = 1; +----+-------------+--------+------+---------------+------+---------+-------+------+--------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------+------+---------------+------+---------+-------+------+--------------------------+ | 1 | SIMPLE | points | ref | id | id | 5 | const | 9 | Using where; Using index | +----+-------------+--------+------+---------------+------+---------+-------+------+--------------------------+