【问题标题】:performance issues executing list of stored procedures执行存储过程列表的性能问题
【发布时间】:2015-06-22 13:58:59
【问题描述】:

我在启动 Windows 服务时遇到了一些性能问题,我的第一轮 lstSps 很长(大约 130 个存储过程)。有没有办法加快速度(除了加快存储过程)?

当 foreach 结束并进入第二轮时,它会更快,因为在 TimeToRun() 上返回 true 的人并不多。但是,我担心的是第一次有更多的存储过程要运行。

虽然我读到它更快,所以我有关于制作一个数组和一个 for 循环的想法,但我认为问题在于这些过程需要很长时间。我可以以更好的方式构建它吗?也许使用多个线程(每个执行一个)或类似的东西?

非常感谢一些提示:)

编辑:澄清一下,它的方法 HasResult() 正在执行 SP:s 并且看起来需要时间..

lock (lstSpsToSend)
{
    lock (lstSps)
    {
        foreach (var sp in lstSps.Where(sp => sp .TimeToRun()).Where(sp => sp.HasResult()))
        {
            lstSpsToSend.Add(sp);
        }
    }
}

while (lstSpsToSend.Count > 0)
{
    //Take the first watchdog in list and then remove it
    Sp sp;
    lock (lstSpsToSend)
    {
        sp = lstSpsToSend[0];
        lstSpsToSend.RemoveAt(0);
    }

    try
    {
        //Send the results
    }
    catch (Exception e)
    {
        Thread.Sleep(30000);
    }
}

【问题讨论】:

  • 只要您没有对其进行分析,我们就无法真正帮助您...
  • 我想要的帮助不是加快所有存储过程,而是找到一种更好的方法来执行它们,所以我没有做 1. 执行所有存储过程(等到全部完成) 2.开始处理结果

标签: c# multithreading performance loops


【解决方案1】:

我会做这样的事情:

int openThread = 0;
ConcurrentQueue<Type> queue = new ConcurrentQueue<Type>();
foreach (var sp in lstSps)
{
    Thread worker = new Thread(() =>
        {
            Interlocked.Increment(ref openThread);
            if(sp.TimeToRun() && sp.HasResult)
            {
                queue.add(sp);
            }
            Interlocked.Decrement(ref openThread);
        }) {Priority = ThreadPriority.AboveNormal, IsBackground = false};
        worker.Start();
}
// Wait for all thread to be finnished
while(openThread > 0)
{
    Thread.Sleep(500);
}

// And here move sp from queue to lstSpsToSend

while (lstSpsToSend.Count > 0)
{
    //Take the first watchdog in list and then remove it
    Sp sp;
    lock (lstSpsToSend)
    {
        sp = lstSpsToSend[0];
        lstSpsToSend.RemoveAt(0);
    }

    try
    {
        //Send the results
    }
    catch (Exception e)
    {
        Thread.Sleep(30000);
    }
}

【讨论】:

  • 不太确定您在那里做了什么,您是否为每个 SP 创建了一个新线程?为什么这会提高性能?
  • 你说是TimeToRun() 让你的东西变慢了,如果你把它放在不同的线程上,让系统并行计算,你会节省时间。我也可以使用Parallel.ForEach。但也许我完全误读了这个问题......@krillezzz
  • 抱歉不够清楚。是 HasResult() 执行 SP:s 并使循环花费时间。
  • @krillezzz 是一样的,现在两者都是并行执行的,应该可以节省一些时间
  • 有了这些结果,我假设你有一些 SP 是重量级的,大多数都是轻量级的。您可以添加日志记录以查看运行时间最长的程序是什么,并查看您是否可以对它们做些什么。
【解决方案2】:

最好的方法将很大程度上依赖于这些存储过程实际上在做什么,如果它们返回相同类型的结果集,或者没有结果,那么一次将它们发送到 SQL Server 肯定是有益的而不是一次一个。

造成这种情况的原因是网络延迟,如果您的 SQL 服务器位于您通过 WAN 访问的某个数据中心中,那么您的延迟可能在 200 毫秒以上。因此,如果您按顺序调用 130 个存储过程,“成本”将是 200 毫秒 X 130。这 26 秒只是通过网络连接来回运行,而不是实际执行过程中的逻辑。

如果您可以将所有过程合并到一个调用中,那么您只需支付一次 200 毫秒的费用。

在多个并发线程上执行它们也是一种合理的方法,但和以前一样,它取决于您的程序正在做什么并返回给您。

在列表上使用数组实际上不会给您带来任何性能提升。

希望这有帮助,祝你好运!

【讨论】:

  • SP:s 如果命中则返回 XML,否则不返回任何内容。如果有命中,则稍后处理 XML。
  • 那么一定要尝试将它们组合成一个 SQL 调用。
  • 但是在一次执行所有结果时如何将结果附加到我的 Sp 对象?
  • 一次性将所有结果作为数据表返回
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多