0

理想的なクラス構造

ゲームには多くのプレイヤーがいて、それぞれが多くの統計を持っています。つまり、それぞれList<Game>に が含まれ、List<Player>それぞれPlayerに が含まれます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()
         });

このソリューションは (明らかに) を使用しません。これは主に、目的の結果を得るために正しい順序で sJoinを実行する方法がわからないためです。Join

毎日、約 10 万の新しいゲーム、約 100 万人のプレイヤー、約 3,000 万の統計情報を集計していることに言及しておく必要があります。現在のクエリは、1 秒あたり最大 1.4 ゲームを選択でき、ハイパー スレッド化されたクアッド コア CPU の 99% を使用します。

何かご不明な点がございましたら、お気軽にお問い合わせください。

更新 #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
         });

この単純なことは、毎秒最大 9,000 行 (元の 22 倍の速さ) を生成することです。SQL Server が明らかにすべての作業を行っており、CPU の約 90% を使用しています。ただし、ネストされたオブジェクトの代わりに、1 次元のクエリが残っています。

この更新について何か提案があれば、ぜひ聞かせてください。

4

2 に答える 2

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 に答える
0

最初に単純な linq 結合を試してください。

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 に答える