我可以“订购”表“排名”而不锁定它吗? (不关心错误)
Posted
技术标签:
【中文标题】我可以“订购”表“排名”而不锁定它吗? (不关心错误)【英文标题】:Can I "Order" table "ranks" without locking it ? (don't care for errors) 【发布时间】:2020-10-03 05:58:52 【问题描述】:我为有“信用”的用户准备了一张大桌子。每隔几分钟我想按信用对用户进行排名。 问题是此操作需要时间并锁定整个表。 由于我不在乎排名中是否存在临时错误,有没有办法在不锁定表的情况下执行此功能?
UPDATE users SET userrank= @r:= (@r+1) ORDER BY credits DESC
【问题讨论】:
这些学分变化的速度有多快?如果您仅在积分或位置实际发生变化时更新排名,您可能会整体更快。您是否需要具体的排名值(1,2,3...),例如用于展示或可以是例如1.5 在 rank 1 和 2 之间插入一行? 由于您将排名存储在表中,因此更新操作将始终锁定所有受影响的记录。如果要存储排名,请考虑使用单独的排名表。这样,当您重新计算排名时,主表不会被锁定。 【参考方案1】:我不建议将排名存储在表格本身中。这是派生信息,可以在需要时轻松即时计算。维护此类信息也很昂贵:每次修改表(更新、插入或删除)时,您可能需要重新排列所有行。
另一种选择是使用视图。如果您运行的是 mysql 8.0,则可以使用窗口函数:
create view v_users as
select u.*, rank() over(order by credits) rn
from users u
请注意,rank()
为平局分配了相同的编号。
在早期版本中,一种替代方法是相关子查询(视图中不支持用户变量):
create view v_users as
select u.*, 1 + (select count(*) from users u1 where u1.credits > u.credits) rn
from users u
【讨论】:
@dani - 如果您尝试其中任何一种方法,请报告与原始更新相比它们的运行速度。 当然。一旦我尝试它们,我会报告回来。视图不会在每次使用时一次又一次地运行吗?【参考方案2】:该表有多少列?您是否对该表进行了一些不需要“排名”的查询并且它们被阻止了?如果是这样,请考虑使用仅包含 3 列的表——用户 ID、排名、信用。
这样,阻塞查询将使用较小的表(因此速度更快),而不会阻塞太多的东西。
请提供SHOW CREATE TABLE
;可能还有其他提示可以帮助您解决问题。
【讨论】:
以上是关于我可以“订购”表“排名”而不锁定它吗? (不关心错误)的主要内容,如果未能解决你的问题,请参考以下文章
我可以在 lambda 中使用 constexpr 值而不捕获它吗?
我可以从 Windows RECT 结构访问宽度和高度而不计算它吗?