いくつかの基本
2 つのテーブルがあり、1 つはユーザーを保持し、もう 1 つはログインのログを保持しています。ユーザー テーブルには 15000 人以上のユーザーが保持され、ログイン テーブルは成長しており、150000 件以上の投稿に達しています。データベースは SQL Server 上に構築されています (Express ではありません)。
ユーザーを管理するために、ObjectDatasource から入力するグリッドビュー (Devexpress の ASPxGridView) を取得しました。
ユーザーが行ったログインの数を要約するときに知っておくべき一般的な注意事項はありますか?
物事は奇妙に遅くなっています。
関連するテーブルを示す図を次に示します。
私はいくつかのことを試しました。
DbDataContext db = new DbDataContext();
// Using foregin key relationship
foreach (var proUser in db.tblPROUsers)
{
var count = proUser.tblPROUserLogins.Count;
//...
}
実行時間: 01:29.316 (1 分 29 秒)
// By storing a list in a local variable (I removed the FK relation)
var userLogins = db.tblPROUserLogins.ToList();
foreach (var proUser in db.tblPROUsers)
{
var count = userLogins.Where(x => x.UserId.Equals(proUser.UserId)).Count();
//...
}
実行時間: 01:18.410 (1 分 18 秒)
// By storing a dictionary in a local variable (I removed the FK relation)
var userLogins = db.tblPROUserLogins.ToDictionary(x => x.UserLoginId, x => x.UserId);
foreach (var proUser in db.tblPROUsers)
{
var count = userLogins.Where(x => x.Value.Equals(proUser.UserId)).Count();
//...
}
実行時間: 01:15.821 (1 分 15 秒)
最高のパフォーマンスを発揮するモデルは、実際には辞書です。ただし、そのような大量のデータを処理するときにこの種のコーディングに「悪い」ものがある場合も、それについて聞きたいオプションがあれば知っています。
ありがとう
================================================== ======
更新 BrokenGlass の例によるモデルを使用
// By storing a dictionary in a local variable (I removed the FK relation)
foreach (var proUser in db.tblPROUsers)
{
var userId = proUser.UserId;
var count = db.tblPROUserLogins.Count(x => x.UserId.Equals(userId));
//...
}
実行時間: 02:01.135 (2 分 1 秒)
これに加えて、単純なクラスを格納するリストを作成しました
public class LoginCount
{
public int UserId { get; set; }
public int Count { get; set; }
}
そしてまとめ方では
var loginCount = new List<LoginCount>();
// This foreach loop takes approx 30 secs
foreach (var login in db.tblPROUserLogins)
{
var userId = login.UserId;
// Check if available
var existing = loginCount.Where(x => x.UserId.Equals(userId)).FirstOrDefault();
if (existing != null)
existing.Count++;
else
loginCount.Add(new LoginCount{UserId = userId, Count = 1});
}
// Calling it
foreach (var proUser in tblProUser)
{
var user = proUser;
var userId = user.UserId;
// Count logins
var count = 0;
var loginCounter = loginCount.Where(x => x.UserId.Equals(userId)).FirstOrDefault();
if(loginCounter != null)
count = loginCounter.Count;
//...
}
実行時間: 00:36.841 (36 秒)
これまでの結論、linq での要約は遅いですが、私はそこに着きました!