如何使用ThreadPool并行化数据库查询?

发布于 2024-09-10 06:44:17 字数 1349 浏览 3 评论 0原文

我正在修复别人的代码,需要很长时间才能在以下代码中返回完整的数据集:

DataTable dt = someLib.GetDataTable("EXEC [dbo].[CMS_Content_GetAllContents]");

// Copy the DataTable data to list.
foreach (DataRow dr in dt.Rows)
{
    ContentInfo aContentDetail = new ContentInfo(
            (int)dr["ID"],
            (string)dr["ContentName"],
            getCategories((int)dr["ID"]),
            null,
            (string)dr["Publisher"],
            (string)dr["Price"],
            false);

    contentInfoList.Add(aContentDetail); ;
}

private string getCategories(int ContentID)
{
    String categories = String.Empty;
    String query = String.Format("EXEC [dbo].[CMS_Content_GetContentCategories] @ID = {0}", ContentID);

    DataTable dt = clsGlobal.GetDataTable(query);

    foreach (DataRow dr in dt.Rows)
    {
        categories = String.Concat((string)dr["ShortDescription"] + ", ");                
    }

    if (categories.EndsWith(", "))
        categories = categories.TrimEnd(new char[] { ',', ' ' });

    return categories;
}

这很可悲,因为 DataTable dt 有超过 1,000 行,我无法从存储过程级别处理它!

我只是想知道是否可以将调用 getCategories(int) 捆绑到 Threadpool.QueueUserWorkItem() 中,以便它可以并行,但不知道如何将字符串返回到来电者?

或者,使用线程池是一个坏主意,因为我听说线程池的工作线程不是为长时间运行的查询(例如数据库调用)而设计的,因为 IOCompletion 端口线程可能无法及时返回,因此工作线程可能会因此而被阻塞?

任何帮助表示赞赏。

I'm bugfixing someone else's code where it takes ages to return the complete dataset in the following code:

DataTable dt = someLib.GetDataTable("EXEC [dbo].[CMS_Content_GetAllContents]");

// Copy the DataTable data to list.
foreach (DataRow dr in dt.Rows)
{
    ContentInfo aContentDetail = new ContentInfo(
            (int)dr["ID"],
            (string)dr["ContentName"],
            getCategories((int)dr["ID"]),
            null,
            (string)dr["Publisher"],
            (string)dr["Price"],
            false);

    contentInfoList.Add(aContentDetail); ;
}

private string getCategories(int ContentID)
{
    String categories = String.Empty;
    String query = String.Format("EXEC [dbo].[CMS_Content_GetContentCategories] @ID = {0}", ContentID);

    DataTable dt = clsGlobal.GetDataTable(query);

    foreach (DataRow dr in dt.Rows)
    {
        categories = String.Concat((string)dr["ShortDescription"] + ", ");                
    }

    if (categories.EndsWith(", "))
        categories = categories.TrimEnd(new char[] { ',', ' ' });

    return categories;
}

It is pathetic as there are over 1,000 rows for the DataTable dt and I cannot deal with it from the stored procedure level!

I'm just wondering if I can bundle the call getCategories(int) into Threadpool.QueueUserWorkItem() such that it can go parallel but dunno how to return the string back to the caller?

Or, is it a bad idea to use Threadpool because I heard that the Threadpool's workers threads are not designed for long running queries such as DB calls as the IOCompletion ports thread may not return in time hence workers are likely to get blocked because of that?

Any help appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦明 2024-09-17 06:44:17

恐怕线程在这种情况下不是答案(在线程池上或线程池外)。修复了对数据库的 1000 次调用。您可能会优化少数用户的响应速度,但响应时间仍然会非常令人痛苦,并且您的应用程序将在非常低的负载下崩溃。

我不知道您对数据库有多少控制权,因此这里有一些跨越几个层的想法:

  1. 用内容拉动类别。您可以创建一个函数来对它们进行字符串分隔,或者使用在一次调用中返回多个数据集的过程。
  2. 立即加载所有类别,并将数据放在内存中。
  3. 更改您的 UI,这样您就不会同时使用 1000 个 CMS 项目。寻呼什么的。

祝你好运。

I'm afraid that threading isn't the answer in this case (on or off the threadpool). Fixing the 1000 calls to the database is. You might optimize the speed of your response for a small number of users, but the response time would still be pretty excruciating, and your app is going to fall over at a very low load.

I don't know how much control you have over the database, so here are some ideas that span a few layers:

  1. Pull the categories with the content. You can either create a func to string delimit them, or use a proc that returns multiple datasets in one call.
  2. Load all the categories up at once, and put the data together in memory
  3. Change your UI so that you aren't using 1000 CMS items at once. Paging or something.

Good luck.

ㄖ落Θ余辉 2024-09-17 06:44:17

不过,问题已经有了答案。但这只是为了可能有所帮助。

您可以将代码“移动”到工作线程中并让它运行。您还可以创建添加事件,一旦线程完成工作,它就会通知您。这样您就可以继续(或将进度条移到末尾,如果有的话?)完成其余的工作。

  1. 这里是如何使用线程。
  2. 这是迄今为止我所喜欢的。

作为旁注,我相信这可以在 SP 中完成(如果您可以共享查询);因此,我将创建一个获取内容详细信息的 SP,并且对于每个 ContentDetailID,我将准备一个逗号分隔的类别列表,然后返回我的结果。

所以,你的电话将是:

DataTable dt = someLib.GetDataTable("EXEC [dbo].[CMS_Content_GetAllContents_Ex]");//Note the _EX in the sp name (0:

Though, the question has been answer. But this is just so it might help.

You can "move" your code inside a worker thread and let it run. You can also create add an event and as soon as the thread finishes the work, it would let you know. This way you can continue(or move the progress bar to the end, if you have any?) with the rest of your work.

  1. Here is how you work with threads.
  2. This is what I love, to date.

As a side note, I believe this can be done in the SP(if you can share the query); therefore I would create an SP that fetches the content detail, and for each ContentDetailID, I would prepare a comma separated list of categories and then return with my result.

So, your call will just be:

DataTable dt = someLib.GetDataTable("EXEC [dbo].[CMS_Content_GetAllContents_Ex]");//Note the _EX in the sp name (0:
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文