【发布时间】:2015-06-16 15:56:18
【问题描述】:
我有一些方法需要从多个数据库中获取统计数据。关键思想是每个表都包含一个 DBName,然后我从它向下钻取到客户端主数据库,调用具有所需数据库名称的存储过程。最后我再次下钻,从客户的项目数据库中获取数据。
总结一下:
我获得了所有云用户的列表。
对于每个用户,我使用其主数据库上的存储过程来获取他的客户 -> 标记为 userClients。
对于每个客户,我使用客户项目数据库中的存储过程来获取他的统计信息。
对于非常少的数据执行大约需要 5-6 秒。
public List<CloudAnalysisDTO> GetCloudAnalysisForPeriod(DateTime FromDate, DateTime ToDate)
{
var users = FindAll();
List<CloudAnalysisDTO> resultsList = new List<CloudAnalysisDTO>();
HashSet<string> userclients = new HashSet<string>();
using (var db = new ProjSQLDataContext(conn))
{
foreach (var user in users)
{
if (user.ID == 0)
continue;
var ids = string.Join(",", db.UserClients.Where(uc => uc.UserId == user.ID).Select(uc => uc.ClientId.ToString()).ToArray());
var mainDB = user.MainDB;
if (mainDB.Length == 0 || ids.Length == 0)
continue;
List<CloudAnalysisDTO> userClients =
db.ExecuteQuery<CloudAnalysisDTO>(@"EXEC CloudUsersAnalysis {0},{1}", mainDB, ids).ToList<CloudAnalysisDTO>();
List<CloudAnalysisDTO> needRemove = new List<CloudAnalysisDTO>();
foreach (var client in userClients)
{
if (!userclients.Contains(user.MainDB + client.ClientID.ToString()))
userclients.Add(user.MainDB + client.ClientID.ToString());
else
{
needRemove.Add(client);
continue;
}
ClientAnalysisDTO clientAnalysisDTO =
db.ExecuteQuery<ClientAnalysisDTO>(@"EXEC CloudClientAnalysis {0},{1},{2}", client.ProjectDB, FromDate, ToDate).SingleOrDefault<ClientAnalysisDTO>();
if (clientAnalysisDTO != null)
{
client.ClientAnalysisDTO = clientAnalysisDTO;
}
client.UserID = user.ID;
client.MainDB = user.MainDB;
}
foreach (var removeDTO in needRemove)
{
userClients.Remove(removeDTO);
}
if (userClients != null && userClients.Count > 0)
resultsList.AddRange(userClients);
}
}
return resultsList;
}
关于我可以做些什么来提高性能的任何想法?
【问题讨论】:
-
看起来我有很多 db 调用。
-
对我来说也是如此,但还有其他方法吗?我不知道足够的 sql 技巧来完成它。也许数据库管理员所做的是每隔一段时间缓存统计信息,但我什至不知道如何做到这一点。
-
您将统计信息拉入 .NET 并在 .NET 中进行循环。
-
如果我没记错的话,这就是我现在正在做的事情。
-
不是你不是。您正在循环调用 DB。这与在一次 DB 调用中获取所需的所有信息然后在 .NET 集合中循环不同。
标签: c# sql algorithm linq linq-to-sql