如何使用ThreadPool并行化数据库查询?
我正在修复别人的代码,需要很长时间才能在以下代码中返回完整的数据集:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
恐怕线程在这种情况下不是答案(在线程池上或线程池外)。修复了对数据库的 1000 次调用。您可能会优化少数用户的响应速度,但响应时间仍然会非常令人痛苦,并且您的应用程序将在非常低的负载下崩溃。
我不知道您对数据库有多少控制权,因此这里有一些跨越几个层的想法:
祝你好运。
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:
Good luck.
不过,问题已经有了答案。但这只是为了可能有所帮助。
您可以将代码“移动”到工作线程中并让它运行。您还可以创建添加事件,一旦线程完成工作,它就会通知您。这样您就可以继续(或将进度条移到末尾,如果有的话?)完成其余的工作。
作为旁注,我相信这可以在 SP 中完成(如果您可以共享查询);因此,我将创建一个获取内容详细信息的 SP,并且对于每个 ContentDetailID,我将准备一个逗号分隔的类别列表,然后返回我的结果。
所以,你的电话将是:
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.
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: