需要帮助构建性能最佳的SQL查询
本文关键字:SQL 查询 最佳 性能 帮助 构建 | 更新日期: 2023-09-27 18:00:30
我正在制作一个监听器,这样我就可以将多个游戏的游戏数据发布到我的服务器上。我会用它来保持客户端的同步,无论他们在什么设备上玩!这部分我已经完成了,使用Entity和Linq进行插入,并在它们被取消同步时加载playerdata。
根据发送的数据,每个到服务器的网络帖子大约需要2-10毫秒。(我希望这很好!)。这主要是FirstOrDefault选择,修改一些数据并保存更改。
但服务器也必须向客户端提供记分牌。"今天/所有时间"answers"仅限所有人/朋友"。
我尝试了一些LinqSQL查询。但当我看到输出时,我真的很害怕它会如何成型(成千上万的用户和数百万的得分记录)。
这里有一个例子:
using (BertEntities BGE = new BertEntities())
{
var query =
(from score in BGE.ScoreTable
join game in BGE.GameSession on score.GameSessionID equals game.ID
join user in BGE.User on game.UserID equals user.ID
where
game.PublicHighScore == true &&
game.Banned == false &&
game.GameID == GameID &&
score.LevelID == level
orderby score.Score descending
select new ScoreResult
{
ID = user.ID,
Name = user.FacebookName,
Score = score.Score,
Streak = score.Streak,
Time = score.Time
}).Skip(skip).Take(count);
return JsonConvert.SerializeObject(query.ToList());
}
这样执行
SELECT TOP (100)
[Project1].[Score] AS [Score],
[Project1].[ID] AS [ID],
[Project1].[FacebookName] AS [FacebookName],
[Project1].[Streak] AS [Streak],
[Project1].[Time] AS [Time]
FROM ( SELECT [Project1].[Score] AS [Score], [Project1].[Streak] AS [Streak], [Project1].[Time] AS [Time], [Project1].[ID] AS [ID], [Project1].[FacebookName] AS [FacebookName], row_number() OVER (ORDER BY [Project1].[Score] ASC) AS [row_number]
FROM ( SELECT
[Filter1].[Score] AS [Score],
[Filter1].[Streak] AS [Streak],
[Filter1].[Time] AS [Time],
[Extent3].[ID] AS [ID],
[Extent3].[FacebookName] AS [FacebookName]
FROM (SELECT [Extent1].[LevelID] AS [LevelID], [Extent1].[Score] AS [Score], [Extent1].[Streak] AS [Streak], [Extent1].[Time] AS [Time], [Extent2].[UserID] AS [UserID], [Extent2].[GameID] AS [GameID]
FROM [dbo].[ScoreTable] AS [Extent1]
INNER JOIN [dbo].[GameSession] AS [Extent2] ON [Extent1].[GameSessionID] = [Extent2].[ID]
WHERE (1 = [Extent2].[PublicHighScore]) AND (0 = [Extent2].[Banned]) ) AS [Filter1]
INNER JOIN [dbo].[User] AS [Extent3] ON [Filter1].[UserID] = [Extent3].[ID]
WHERE ([Filter1].[GameID] = @p__linq__0) AND ([Filter1].[LevelID] = @p__linq__1)
) AS [Project1]
) AS [Project1]
WHERE [Project1].[row_number] > 0
ORDER BY [Project1].[Score] DESC
我不是SQL专家,但这对我来说很难
这是数据库布局:www.invokergame.com/db.png
我正在考虑将我需要的所有数据存储在ScoreTable表中,这样我就可以避免进行联接。但这会导致大量重复的数据,我敢肯定这是错误的方法。
也许我应该忘记Entity Linq,用ADO.NET SQL编写它(我需要帮助)?
对不起,文字墙,我期待着一些明智的话语!
编辑:
好吧,汤姆,这是你假装的吗?将我需要的所有数据拖放到一个数据集中。然后,当用户创建新的highscore或禁用PublicHighScore时,使用LINQ更新或删除并从此列表中选择项目?
这将如何表现?
public class ScoreCacheItem
{
public Int64 ScoreTableID { get; set; }
public Guid GameID { get; set; }
public int LevelID { get; set; }
public Int64 UserID { get; set; }
public string Name { get; set; }
public int Score { get; set; }
public int Streak { get; set; }
public double Time { get; set; }
public DateTime Today { get; set; }
public int Today_Score { get; set; }
public int Today_Streak { get; set; }
public double Today_Time { get; set; }
}
public sealed class ScoreCacheSystem
{
private List<ScoreCacheItem> FScoreCache = new List<ScoreCacheItem>();
private object FLock = new object();
private List<ScoreCacheItem> LoadAllScores()
{
using (BertEntities BGE = new BertEntities())
{
var query =
(from score in BGE.ScoreTable
join game in BGE.GameSession on score.GameSessionID equals game.ID
join user in BGE.User on game.UserID equals user.ID
where
game.PublicHighScore == true &&
game.Banned == false
orderby score.Score descending
select new ScoreCacheItem
{
ScoreTableID = score.ID,
GameID = game.GameID,
LevelID = score.LevelID,
UserID = user.ID,
Name = user.FacebookName,
Score = score.Score,
Streak = score.Streak,
Time = score.Time,
Today = score.Today,
Today_Score = score.Today_Score,
Today_Streak = score.Today_Streak,
Today_Time = score.Today_Time
});
return query.ToList();
}
}
public List<ScoreCacheItem> HighScores {
get
{
lock (FLock)
{
if (FScoreCache == null)
{
FScoreCache = LoadAllScores();
}
return FScoreCache;
}
}
}
}
您在SQL端有一个严重的问题。EF的SQL做得很好,但在这里我认为SQL Server的使用通常是不好的。
如果您需要快速回答这种类型的查询,那么可以从内存中进行,而不是从数据库服务器中进行。内存中查找通常用于简单的查询,这些查询对数据分发具有重复性和时间敏感性(金融交易-没有人会将价格写入数据库,然后让客户提取价格;您在将价格写入商店的同时分发价格)。
否则你就可以伪造它——缓存出现在我的脑海中。使用这种体系结构,您无法优化对重要数据库服务器的需求。确保你的索引已经到位。根据查询计划进行操作,确保不会遗漏任何内容。
但实际上,要尽量避免在所有级别都影响SQL Server的缓存输出。顺便说一句,SQL非常琐碎。当你点击2-3个屏幕长的分析查询时,事情会变得有趣;)数以百万计的记录不是问题,主要问题将是并发请求。连接最好已读取已提交的隔离,以确保您没有设置锁。然后获得一个合适的服务器并进行扩展,除非您更改体系结构。
我想把我需要的所有数据都存储在ScoreTable表中,所以我会避免加入。但这会导致大量重复数据,我很确定这是错误的方法。
绝对不是——就像不是错误的方法。非规范化是读取量大的报告数据库中的典型情况。您可以使用触发器来自动维护此表。它在你的情况下是否有意义,必须用一个好的数据集来测试。这通常并不糟糕,但却是数据仓库的标准做法,尽管这些通常处理实际数量的数据(数十亿行,而不是像一百万或两行这样的微小数据)。在我上一个更大的数据仓库项目中,我们每天加载大约4.5亿行,并且必须将它们存档10年才能进行报告。在谷歌上查找"星型模式"。基本上只读/数据仓库场景的规则不同。