0

理想的班级结构

一个游戏有很多玩家,每个玩家都有很多统计数据。换句话说,每个都List<Game>包含 aList<Player>并且每个都Player包含 a List<Statistic>

Game -> Player1 -> Statistic1
                   ....
                   Statistic30
        ....
        Player10 -> Statistic1
                    ....
                    Statistic30

基本表架构

Game
----
GameId (int)
Region (nvarchar(4))

Player
------
GameId (int)
Region (nvarchar(4))
AccountId (int)

Statistic
---------
GameId (int)
Region (nvarchar(4))
AccountId (int)

我的尝试

var b = (from g in db.Games
         select new GameDTO()
         {
             GameId = g.GameId,
             Players = (from p in db.PlayerGames
                        where p.GameId == g.GameId && p.Region.Equals(g.Region)
                        select new PlayerGameDTO()
                        {
                            AccountId = p.AccountId,
                            GameId = p.GameId,
                            Region = p.Region,
                            Statistics = (from r in db.Statistics
                                          where r.AccountId == p.AccountId && r.GameId == p.GameId && r.Region.Equals(p.Region)
                                        select r).ToList()
                        }).ToList()
         });

该解决方案(显然)不使用Join,主要是因为我不确定如何以Join正确的顺序执行 s 以获得所需的结果。

我应该提一下,我们每天汇总约 10 万新游戏、约 100 万玩家和约 3000 万统计数据。当前查询每秒可以选择约 1.4 个游戏,并使用 99% 的超线程四核 CPU。

如果有什么不清楚的地方,请随时要求澄清。

更新#1

var d = (from g in db.Games
         join p in db.PlayerGames on new { g.GameId, g.Region } equals new { p.GameId, p.Region }
         join r in db.Statistics on new { p.GameId, p.Region, p.AccountId } equals new { r.GameId, r.Region, r.AccountId }
         select new StatisticsDTO()
         {
             GameId = r.GameId, 
             AccountId = r.AccountId, 
             StatType = r.StatType,
             Value = r.Value
         });

这么简单的事情就是每秒产生约 9K(比原来快 22 倍)行。SQL Server 显然正在使用约 90% 的 CPU 完成所有工作。但是,我留下的是一维查询,而不是嵌套对象。

如果您对此更新有任何建议,我很想听听。

4

2 回答 2

0

首先尝试一个简单的 linq join。

Game
----
GameId (int)
Region (nvarchar(4))

Player
------
GameId (int)
Region (nvarchar(4))
AccountId (int)

Statistic
---------
GameId (int)
Region (nvarchar(4))
AccountId (int)
var b = (from t in db.Games
         join t1 in t.Player on t.GameId equals t1.GameId
         join t2 in t.Statistic on t.GameId equals t2.GameId
         select new PlayerGameDTO
         {
            AccountId = t1.AccountId,
            GameId = t1.GameId,
            Region = t1.Region,
            //RawStats <-- what are you trying to do here?
            //RawStats = (from r in db.RawStats
            //where r.AccountId == p.AccountId && r.GameId == p.GameId && r.Region.Equals(p.Region) select r).ToList()
         }).ToList();
于 2013-01-16T01:13:35.873 回答
0

听起来让您的数据库处理其中的一些工作负载可能更合适,特别是如果您只是运行查询而不是写入数据库。考虑在您的数据库中创建一个实现连接的视图。然后您可以查询视图并避免加入您的客户端计算机。您仍然可以使用实体数据模型和 LINQ 对视图运行查询。使用这种方法,您应该会看到相当不错的性能提升。

//Possible SQL for creating the view
CREATE VIEW vw_GameData AS 
SELECT g.GameId, g.Region, p.AccountId, etc...
FROM Game g JOIN Player p ON (g.GameId = p.GameId AND g.Region = p.Region)
JOIN Statistic s ON (s.GameId = p.GameId AND s.RegionId = p.RegionId AND s.AccountId = p.AccountId)
于 2013-01-16T00:57:26.453 回答