对于排名系统(在拥有数万用户的数据库中),我想按用户总数排列三列: Points_A
,Points_B
和Points_C
。我想知道这将是一个更好的选择:总列或新列
- 每个被访问排名网页时,通过总和所有列和顺序相加计算用户的排名
- 创建一个新列
Points_total
与三列的总和(我每次更新其他列之一时更新总数),并按此Points_total
排序查询。
排名页面可能每秒要求多次,所以表现非常重要。第二种选择更快还是不推荐?
对于排名系统(在拥有数万用户的数据库中),我想按用户总数排列三列: Points_A
,Points_B
和Points_C
。我想知道这将是一个更好的选择:总列或新列
Points_total
与三列的总和(我每次更新其他列之一时更新总数),并按此Points_total
排序查询。排名页面可能每秒要求多次,所以表现非常重要。第二种选择更快还是不推荐?
从MySQL 5.7.6开始,您可以创建生成的列,使您能够根据表中其他列中的其他值存储虚拟值。
CREATE TABLE tbl (
Points_A INT,
Points_B INT,
Points_C INT,
Points_total INT AS (Points_A + Points_B + Points_C)
);
生成列定义具有以下语法:
COL_NAME DATA_TYPE [总是GENERATED] AS(表达式)
[VIRTUAL | STORED] [UNIQUE [KEY] [注释评论]
[NOT] NULL] [PRIMARY] KEY]
您可以决定使用VIRTUAL
或STORED
(取决于你的需要)。
从MySQL 5.7.8开始,你也可以添加INDEXes on virtual columns,所以在你的情况下 - 这正是你正在寻找的(这种方式列中的值被索引)。
如果您使用的是比5.7.8更早的MySQL,并且多次访问排名页面 - 我建议您将特定列中的计算值相同并在该列上添加索引。
如果OP有成千上万的用户,那么需求可能需要一个索引。 –
注意:某些时候(数百万用户?)重复更新索引的成本将会过高。成本本质上是“从BTree(索引)中删除一行并将其重新插入到其他地方”。 –
这是一个想法。而不是在排名的每一个变化上采取昂贵的行动,看看这个复杂的方法可能会更好:
但首先,这取决于Points
只增加,从不减少。它还假定你只需要排在前10名。并且不关心发现“我在10000中排名7654”)
设置一个触发器(或应用程序代码),每当排名增加时都会作出反应。它将点加在一起并根据阈值进行检查。如果低于第10位的值,则不要做任何事情。
如果更高,则执行SELECT ... ORDER BY ... LIMIT 10
以获得新的“前10位”并将结果存储在单独的表中。另外,更新阈值。
的可能好处:
query_cache_size = 20M
(不要太大),query_cache_type = DEMAND
SQL_CACHE
到基层SELECT
;将SQL_NO_CACHE
添加到其他大多数SELECTs
。如果你需要的不仅仅是一个的“前10名”页多,考虑到节约“前50名”。对于前5页,新表就足够了。对于第6页及更高版本,请以硬方式进行(扫描10K行表格)。希望这将会是非常罕见的,仍然是一个优势。
最好的办法就是试试更简单的方法(不存储总和),看看性能是否可以接受*。不是哪一个更好,因为不管多困难多少,比方说,它的速度要快1000倍,比如它需要从120毫秒到少于一飞秒的延迟,120毫秒对于一个页面来说足够快加载。即只有在显着影响用户体验的情况下,性能才非常重要。 –