Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从运行缓慢的多个数据库获取数据的方法_C#_Sql_Algorithm_Linq_Linq To Sql - Fatal编程技术网

C# 从运行缓慢的多个数据库获取数据的方法

C# 从运行缓慢的多个数据库获取数据的方法,c#,sql,algorithm,linq,linq-to-sql,C#,Sql,Algorithm,Linq,Linq To Sql,我有一些方法需要从多个数据库获取统计数据。关键的想法是每个表都有一个DBName,从中我深入到客户机主DB,用所需的数据库名调用存储的proc。最后,我再次向下钻取以从客户的项目数据库中获取数据 总而言之: 我得到了所有云用户的列表 对于每个用户,我使用其主数据库上的存储过程->标记为userClients来获取其客户机 对于每个客户机,我使用客户机项目数据库上的存储过程获取其统计信息 对于很少的数据,执行大约需要5-6秒 public List<CloudAnalysisDTO>

我有一些方法需要从多个数据库获取统计数据。关键的想法是每个表都有一个DBName,从中我深入到客户机主DB,用所需的数据库名调用存储的proc。最后,我再次向下钻取以从客户的项目数据库中获取数据

总而言之:

  • 我得到了所有云用户的列表

  • 对于每个用户,我使用其主数据库上的存储过程->标记为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;
        }
    
    公共列表GetCloudAnalysisForPeriod(DateTime FromDate,DateTime ToDate)
    {
    var users=FindAll();
    列表结果列表=新列表();
    HashSet userclients=newhashset();
    使用(var db=newprojsqldatacontext(conn))
    {
    foreach(用户中的var用户)
    {
    如果(user.ID==0)
    继续;
    var ID=string.Join(“,”,db.UserClients.Where(uc=>uc.UserId==user.ID)。选择(uc=>uc.ClientId.ToString()).ToArray();
    var mainDB=user.mainDB;
    if(mainDB.Length==0 | | ids.Length==0)
    继续;
    列出用户客户端=
    ExecuteQuery(@“execcloudusersananalysis{0},{1}),mainDB,ids.ToList();
    List needRemove=新列表();
    foreach(userClients中的var客户端)
    {
    如果(!userclients.Contains(user.MainDB+client.ClientID.ToString())
    添加(user.MainDB+client.ClientID.ToString());
    其他的
    {
    needRemove.Add(客户端);
    继续;
    }
    ClientAnalysisDTO ClientAnalysisDTO=
    ExecuteQuery(@“EXEC CloudClientAnalysis{0}、{1}、{2}”、client.ProjectDB、FromDate、ToDate).SingleOrDefault();
    if(clientAnalysisDTO!=null)
    {
    client.ClientAnalysisDTO=ClientAnalysisDTO;
    }
    client.UserID=user.ID;
    client.MainDB=user.MainDB;
    }
    foreach(needRemove中的var removeDTO)
    {
    userClients.Remove(removeDTO);
    }
    if(userClients!=null&&userClients.Count>0)
    resultsList.AddRange(用户客户端);
    }
    }
    返回结果列表;
    }
    

    我能做些什么来提高性能呢?

    我要做的第一件事是启用.NET跟踪,并在每次调用前后向tracelog写一行

    这一行让我怀疑您可能在其中一个查询中秘密运行了一个“in”子句,这可能会导致性能下降:

     var ids = string.Join(",", db.UserClients.Where(uc => uc.UserId == user.ID).Select(uc => uc.ClientId.ToString()).ToArray());
    

    下一步,一旦您发现性能不佳的执行者(上面这一行只是我的猜测),您应该启用数据库分析,以确定哪里需要新的索引或数据库维护。

    对我来说,似乎有很多db调用。对我来说,也是如此,但还有其他方法吗?我不知道足够的sql技巧来实现它。也许数据库管理员所做的是每隔一段时间缓存统计数据,但我甚至不知道该怎么做。你把统计数据拉到.NET中,然后在.NET中循环。如果我没弄错的话,我现在就是这么做的。不是你不是。您正在循环调用DB。这与在一次DB调用中获取所需的所有信息,然后在.NET集合中循环不同。我在第一次存储过程中使用了“in”子句!相反,我可以做的是创建一个循环,并使用常规where从.Net中逐个获取用户客户端。但我不认为这是它运行速度慢得多的原因。这意味着调用存储过程的次数会更多,您可以在视图或单个存储过程中引用JOIN语句中的每个数据库。您只需参考databasename.schema.table,例如:“myDB.dbo.myTable”。将其放在单个过程中可以让服务器处理优化。(看起来您在一个服务器实例上,如果我错了,您需要添加一个链接服务器)。除此之外,请确保您在所加入的任何内容中引用索引字段。我不知道如何这样做,因为每个用户行都有一个不同的mainDB列。连接需要在该列的值上。所以Join[this is value]->(mainDB).dbo.myTable打开(这里是什么?)