数据库排名位置。性能问题
Database rankings positions. Performance problem
我在检索三个游戏排名时遇到性能问题。下面的代码运行大约 300 毫秒,这对我的经理来说太长了。
public async Task<PointsDto> UserPoints(int userId, int countryId)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
var userData = await context.UsersProfile
.AsNoTracking()
.Select(x => new { x.SeasonPoints, x.RankingPoints, x.Id })
.FirstOrDefaultAsync(x => x.Id == userId);
var seasonPlace = await context.UsersProfile
.Select(x => x.SeasonPoints)
.Where(x => x > userData.SeasonPoints)
.CountAsync();
var regionPlace = await context.Users
.Include(x => x.UserProfile)
.Select(x => new { x.UserProfile.RankingPoints, x.CountryId })
.Where(x => x.CountryId == countryId && x.RankingPoints > userData.RankingPoints)
.CountAsync();
var worldPlace = await context.UsersProfile
.Select(x => x.RankingPoints)
.Where(x => x > userData.RankingPoints)
.CountAsync();
var result = new PointsDto()
{
RankingPoints = userData.RankingPoints,
SeasonPoints = userData.SeasonPoints,
RegionPlace = regionPlace + 1,
SeasonPlace = seasonPlace + 1,
WorldPlace = worldPlace + 1
};
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
return result;
}
我尝试下载所有用户并统计他们。然后就更好用了,但是恐怕到时候有1,000,000用户,至少有1/10会下载这么多数据,内存负担会很重。能把执行时间减半就好了,现在不知道怎么办了。
出于性能原因,我会将其委托给 Sql 服务器 TVF。种类
create function Ranking(@userId int, @countryId int)
returns table
as
return
with userdata as (
select SeasonPoints, RankingPoints
from UsersProfile
where Id = @userId
)
select count(case when x.SeasonPoints > userData.SeasonPoints then x.Id end) seasonPlace,
count(case when x.CountryId = @countryId and x.RankingPoints > userData.RankingPoints then x.Id end) regionPlace,
count(case when x.RankingPoints > userData.RankingPoints then x.Id end) worldPlace,
from UsersProfile x
join userData on (x.RankingPoints > userData.RankingPoints
or x.SeasonPoints > userData.SeasonPoints);
如果缺少索引,查询优化器会建议适当的索引。
我在检索三个游戏排名时遇到性能问题。下面的代码运行大约 300 毫秒,这对我的经理来说太长了。
public async Task<PointsDto> UserPoints(int userId, int countryId)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
var userData = await context.UsersProfile
.AsNoTracking()
.Select(x => new { x.SeasonPoints, x.RankingPoints, x.Id })
.FirstOrDefaultAsync(x => x.Id == userId);
var seasonPlace = await context.UsersProfile
.Select(x => x.SeasonPoints)
.Where(x => x > userData.SeasonPoints)
.CountAsync();
var regionPlace = await context.Users
.Include(x => x.UserProfile)
.Select(x => new { x.UserProfile.RankingPoints, x.CountryId })
.Where(x => x.CountryId == countryId && x.RankingPoints > userData.RankingPoints)
.CountAsync();
var worldPlace = await context.UsersProfile
.Select(x => x.RankingPoints)
.Where(x => x > userData.RankingPoints)
.CountAsync();
var result = new PointsDto()
{
RankingPoints = userData.RankingPoints,
SeasonPoints = userData.SeasonPoints,
RegionPlace = regionPlace + 1,
SeasonPlace = seasonPlace + 1,
WorldPlace = worldPlace + 1
};
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
return result;
}
我尝试下载所有用户并统计他们。然后就更好用了,但是恐怕到时候有1,000,000用户,至少有1/10会下载这么多数据,内存负担会很重。能把执行时间减半就好了,现在不知道怎么办了。
出于性能原因,我会将其委托给 Sql 服务器 TVF。种类
create function Ranking(@userId int, @countryId int)
returns table
as
return
with userdata as (
select SeasonPoints, RankingPoints
from UsersProfile
where Id = @userId
)
select count(case when x.SeasonPoints > userData.SeasonPoints then x.Id end) seasonPlace,
count(case when x.CountryId = @countryId and x.RankingPoints > userData.RankingPoints then x.Id end) regionPlace,
count(case when x.RankingPoints > userData.RankingPoints then x.Id end) worldPlace,
from UsersProfile x
join userData on (x.RankingPoints > userData.RankingPoints
or x.SeasonPoints > userData.SeasonPoints);
如果缺少索引,查询优化器会建议适当的索引。