2013-05-08 125 views
1

循环我有一个代码,一些这样的事通过优化数据集

dxMemOrdered : TdxMemData; 
while not qrySandbox2.EOF do 
    begin 
     dxMemOrdered.append; 
     dxMemOrderedTotal.asCurrency := qrySandbox2.FieldByName('TOTAL').asCurrency; 
     dxMemOrdered.post; 
     qrySandbox2.Next; 
    end; 

这个代码在一个线程中执行。当有大量记录说“400000”时,大约需要25分钟来解析它。有没有什么办法可以通过优化循环来缩小尺寸?任何帮助,将不胜感激。

更新

基础上的建议,我做了以下修改

dxMemOrdered : TdxMemData; 
qrySandbox2.DisableControls; 
while not qrySandbox2.Recordset.EOF do 
    begin 
     dxMemOrdered.append; 
     dxMemOrderedTotal.asCurrency := Recordset.Fields['TOTAL'].Value; 
     dxMemOrdered.post; 
     qrySandbox2.Next; 
    end; 
qrySandbox2.EnableControls; 

和我的输出时间从15分钟到2分钟提高。谢谢你们

+1

这是TdxMemData – Jeeva 2013-05-08 08:47:22

+2

使用'try..finally'块作为@whosrdaddy在他的答案。我提到的前向游标可能会帮助您改进从源数据集中读取数据。 – TLama 2013-05-08 11:59:43

回答

2

一些想法在性能增益VS工作,以便通过你做:

1)检查,如果您正在使用的SQL方言,您可以使用直接从/ INSERT到SELECT查询。这取决于你使用的数据库。

2)确保,如果你的数据集未连接到可视控件,您致电解决这个循环

3 DisableControls/EnableControls)这个代码必须在程序主线程中运行?也许你可以发送一个单独的线程,而用户/程序继续执行其他操作。

4)当你必须处理真正的大数据时,批量插入是要走的路。许多数据库都有从文本文件批量插入数据的选项。首先写入文本文件,然后批量插入比单独插入更快。再次,这取决于你的数据库类型。

[编辑:我只是看到你插入信息,它是TdxMemData,所以其中一些不再适用。你已经穿线了,错过了;-)。我将这些建议留给其他类似问题的读者]

+0

OP已经使用了一个线程。所以对于这个问题仍然有效的唯一一点是在我的观点2中。但除了第2点,你可能会建议使用某种只读向前游标(取决于数据库)。 [+1] – TLama 2013-05-08 08:56:57

+0

用答案更新了我的问题。 – Jeeva 2013-05-08 10:26:31

+0

@Jeeva,你也有通过dxMemOrdered链接的控件吗? – whosrdaddy 2013-05-08 10:55:26

2

没有看到更多的代码,我唯一可以做的建议是确保任何正在使用内存表的可视化控件都被禁用。假设你有一个名为Grid cxgrid链接到您的dxMemOrdered内存表:

var  
    dxMemOrdered: TdxMemData; 
... 

Grid.BeginUpdate; 
try 
    while not qrySandbox2.EOF do 
    begin 
    dxMemOrdered.append; 
    dxMemOrderedTotal.asCurrency := qrySandbox2.FieldByName('TOTAL').asCurrency; 
    dxMemOrdered.Post; 
    qrySandbox2.Next; 
    end; 
finally 
    Grid.EndUpdate; 
end; 
+0

所以这同样的规则适用于甚至解析TdxMemData?或者我们应该怎么做 – Jeeva 2013-05-09 11:18:58

0

这是更好的让SQL做的工作,而不是迭代虽然在Delphi中循环。尝试查询如

insert into dxMemOrdered (total) 
select total from qrySandbox2 

'total'是dxMemOrdered中唯一的字段吗?我希望它不是主键,否则你可能会发生碰撞,这意味着行不会被添加。

+2

这不会工作,因为dxMemOrdered是一个Tdxmemdata组件(inmemory表) – whosrdaddy 2013-05-08 12:54:13

0

实际上你可以做很多事情来加速你的线程。

第一是看问题更广泛的角度:

  • 我是不是从缓存/快盘,内存可能是移动中获取数据?

  • 我正在做正确的事情,当手动汇总总计?SQL引擎特别针对这些问题进行了优化,您只需要定义一个额外的逻辑字段来存储SQL聚合结果。

,可能对大量的循环带来的另一个改进小优化是不使用结构,如:

  • Recordset.Fields [“总”]值

  • 记录.FieldByName('TOTAL')。值

但添加字段的字段编辑器然后直接访问正确的字段。您将通过字段集合保存整个循环,否则每个字段都会在每个下一个记录上执行。