所以我的问题是,如何和什么应该并行化?
这些是原始查询(缩写为必需):
'check for new data Dim srcUnique = From row In src.Email_Total Select Ticket_ID = row.ticket_id,Interaction = row.interaction,ModifiedAt = row.modified_time Dim destUnique = From row In dest.ContactDetail Where row.ContactRow.fiContactType = emailContactType.idContactType Select row.ContactRow.Ticket_ID,row.Interaction,row.ModifiedAt 'get all emails(contactdetails) that are in source but not in destination Dim diffRows = srcUnique.Except(destUnique).ToList 'get all new emails(according to ticket_id) for calculating contact columns Dim newRowsTickets = (From row In src.Email_Total Join d In diffRows On row.ticket_id Equals d.Ticket_ID _ And row.interaction Equals d.Interaction _ And row.modified_time Equals d.ModifiedAt Group row By Ticket_ID = row.ticket_id Into NewTicketRows = Group).ToList For Each ticket In newRowsTickets Dim contact = dest.Contact.FindByTicket_IDfiContactType(ticket.Ticket_ID,emailContactType.idContactType) If contact Is Nothing Then ' Create new Contact with many sub-queries on this ticket(omitted) ****' Dim newContact = Me.dest.Contact.NewContactRow dest.Contact.AddContactRow(newContact) contact = newContact Else ' Update Contact with many sub-queries on this ticket(omitted) ' End If daContact.Update(dest.Contact) ' Add new ContactDetail-Rows from this Ticket(this is the counterpart of the src.Email_Total-Rows,details omitted) ' For Each newRow In ticket.NewTicketRows Dim newContactDetail = dest.ContactDetail.NewContactDetailRow newContactDetail.ContactRow = contact dest.ContactDetail.AddContactDetailRow(newContactDetail) Next daContactDetails.Update(dest.ContactDetail) Next
注意:daContact和daContactDetails是sqlDataAdapters,source和dest是DataSet,Contact和ContactDetail是DataTable,每个ContactDetail都属于一个Contact.
即使不是这两个核心都不会使用100%的cpu,我认为如果我并行化查询,那么它会显着提高性能,因为第二个核心几乎处于空闲状态.对于每一个都可能是一个优化的地方,因为票不相关.所以我假设我可以循环多个线程并创建/更新记录并行.但是如何使用PLINQ?
侧面注意:正如我在评论中提到的,性能不是我迄今为止的关键因素,因为服务器的唯一目的是同步MysqL数据库(在另一台服务器上)与MS sql Server(在同一台服务器上)作为这个Windows服务).它作为由另一个服务生成的报告的来源.但这些报告只能每天生成一次.但除此之外,我有兴趣学习PLINQ,因为我认为这可能是一个很好的锻炼.
仅当目标数据库为空并且必须创建所有记录时,才需要提到的1,5h.如果两个数据库几乎同步,这个方法只需要1分钟左右.在未来的表现将变得更加重要,因为电子邮件只是几种联系人类型之一(聊天通话将超过1mil.records).我认为我会反正需要某种(LINQ)数据分页.
如果不清楚,我会相应地更新我的答案.提前致谢.
编辑:这是我调查和尝试的结果:
问题:如何使用联接“PLINQ”现有的LINQ查询?
Answer:请注意,一些LINQ运算符是二进制的,它们以两个IEnumerables为输入.加入是这样一个运算符的完美例子.在这些情况下,最左侧数据源的类型决定是使用LINQ还是PLINQ.因此,您只需要在第一个数据源上调用AsParallel,使您的查询并行运行:
IEnumerable<T> leftData = ...,rightData = ...; var q = from x in leftData.AsParallel() join y in rightData on x.a == y.b select f(x,y);
但是如果我以下列方式更改查询(请注意AsParallel):
Dim newRowsTickets = (From row In src.Email_Total.AsParallel() Join d In diffRows On row.ticket_id Equals d.Ticket_ID _ And row.interaction Equals d.Interaction _ And row.modified_time Equals d.ModifiedAt Group row By Ticket_ID = row.ticket_id Into NewTicketRows = Group).ToList
编译器会抱怨我需要将AsParallel添加到正确的数据源.所以这似乎是一个VB.NET问题或缺乏文档(文章来自2007).我认为后者是因为(除了那个可推荐的)文章还说你需要手动添加System.Concurrency.dll,但实际上它是.NET 4.0 Framework和命名空间Sytem.Threading.Tasks的一部分.
我意识到我不会从并行获利.除了在顺序模式下查询足够快(即使两个集合中几乎相同的行数导致最大的比较数量,我得到的结果不到30秒).但是,为了完整起见,我会补充一下.
所以我决定并行化每个与LINQ-Queries一样简单的东西,你只需要在最后添加AsParallel().
但是我意识到我需要强制使用WithExecutionMode(ParallelExecutionMode.ForceParallelism)的并行性,否则.NET决定在此循环中只使用一个内核.我也想告诉.NET,我希望使用尽可能多的线程,但不要超过8:WithDegreeOfParallelism(8).
现在,两个内核都在同一时间工作,但cpu占用率仍然保持在54%.
所以这是PLINQ版本到目前为止
Dim diffRows = srcUnique.AsParallel.Except(destUnique.AsParallel).ToList Dim newRowsTickets = (From row In src.Email_Total.AsParallel() Join d In diffRows.AsParallel() On row.ticket_id Equals d.Ticket_ID _ And row.interaction Equals d.Interaction _ And row.modified_time Equals d.ModifiedAt Group row By Ticket_ID = row.ticket_id Into NewTicketRows = Group).ToList For Each ticket In newRowsTickets. AsParallel(). WithDegreeOfParallelism(8). WithExecutionMode(ParallelExecutionMode.ForceParallelism) ' blah,blah ... ' 'add new ContactDetails for this Ticket(only new rows) For Each newRow In ticket.NewTicketRows. AsParallel(). WithExecutionMode(ParallelExecutionMode.Default) ' blah,blah ... ' Next daContactDetails.Update(dest.ContactDetail) Next
不幸的是,与顺序模式相比,使用AsParallel没有任何性能优势:
对于每个与AsParallel(hh:mm:ss.mm):
09/29/2011 18:54:36: Contacts/ContactDetails created or modified. Duration: 01:21:34.40
没有:
09/29/2011 16:02:55: Contacts/ContactDetails created or modified. Duration: 01:21:24.50
有人可以解释一下这个结果吗?数据库的写入访问是否为每个负责类似的时间?
以下是推荐读物:
> http://msdn.microsoft.com/en-us/magazine/cc163329.aspx(不可更新)
> List of changes since above article
> Overview of videos/articles according this topic
> PDF: When To Use ParallelForEach Or PLINQ
> When PLINQ will speedup performance
解决方法
>不要使用.toList().我可能是错的,但我认为使用.ToList
这样就不允许编译器优化查询,如果
进一步优化是可能的.
>使用您自己的过滤操作来比较两者的数据
destionations.它可能会给你更好的表现.
看看是否可以使用LinqDataview提供更好的
性能.
我不认为你在插入时会获得PLinq的优势.查看this answer了解更多详情.
希望有帮助.如果您需要澄清以上任何一点,请咨询.