0

我有一个数据库表 UserRewards 有 30+ 百万行。在这一行中,每行有一个用户 ID 和一个奖励 ID(以及其他字段)。

有一个 users 表(有大约 400 万唯一用户),它具有主键 userID 和其他字段。出于性能原因,我想将 userrewards 中每个用户的奖励 ID 移动到 users 中的串联字段中。(名为 Rewards 的新 nvarchar(4000) 字段)我需要一个可以尽快完成此操作的脚本。

我有一个光标,它使用下面的脚本来连接奖励,但它每分钟只处理大约 100 个用户,这需要很长时间才能通过我拥有的大约 400 万唯一用户。

 set @rewards = ( select REPLACE( (SELECT rewardsId AS [data()] from userrewards
 where UsersID = @users_Id and BatchId = @batchId
       FOR XML PATH('')  ), ' ', ',') )

有什么建议可以优化吗?我将尝试一个 while 循环,看看它是如何工作的,但任何其他想法都会受到极大的欢迎。

编辑:

我的网站执行以下操作:

我们有大约 400 万用户,他们已经预先分配了 5-10 个“奖励”。这种关系在 userrewards 表中。

用户来到网站,我们识别他们,并在数据库中查找分配给他们的奖励。

问题是,该站点非常受欢迎,因此我有大量的人同时访问该站点以请求他们的数据。以上将减少我的加入,但我知道这可能不是最好的解决方案。我的数据库服务器在打开站点后的 10 秒内达到 100% 的 CPU 使用率,因此大多数人的请求超时(显示错误页面),或者他们得到结果,但不是在令人满意的时间。

有人可以为我的问题提出更好的解决方案吗?

4

2 回答 2

1

我认为您尝试的方法是一个坏主意有几个原因。首先,您将如何维护 users 表中的逗号分隔列表?奖励可能是批量加载的,比如在晚上,所以现在这不是问题。即便如此,有一天您可能希望更频繁地分配奖励。

其次,当您想删除奖励或更改其中之一的名称时会发生什么?您需要更新两个不同位置的信息,而不是更新一个表。

如果你有 400 万用户,有数千个并发访问,那么由于时间而导致的小不一致会很明显,并且可能会引起用户投诉。首席执行官打来的关于投诉为何增加的电话可能不是您想要处理的事情。

另一种方法是在 UserRewards(UserId, BatchId, RewardsId) 上建立索引。据推测,每个字段只有几个字节,因此 3000 万条记录应该很容易放入 8 GB 的内存中(确保 SQL Server 分配了几乎所有的内存!)。您想要的查询可以通过此索引严格满足,而无需将 UserRewards 表放入内存。所以,只有索引需要被缓存。并且,它将针对此查询进行优化。

可能会减慢一切的一件事是分配奖励的频率。如果这些被分配甚至是读取率的 10%,那么您可能会让插入/更新阻塞读取。您想使用 READ_NOLOCK 进行查询,以避免此问题。您还希望确保在记录或页面级别发生锁定,以避免与读取发生冲突。

于 2012-11-30T21:31:20.477 回答
0

也许为时已晚,但使用 uniqueidentifiers 作为键不仅会使您的存储空间增加四倍(与使用整数作为键相比),而且会使查询速度降低几个数量级。避免!!!

于 2013-01-20T20:35:03.647 回答