谁能帮我把这段代码优化一下,以提高效率?
var
i,j:integer;
begin
ADODataSetFenbu.DisableControls;
for j:=1 to 30 do
begin
ADODataSetFenbu.first;
i:=0;
while not ADODataSetFenbu.Eof do
begin
if ADODataSetFenbu.FieldByName('No'+inttostr(j)).asstring = '' then
begin
i:=i+1;
ADODataSetFenbu.edit;
ADODataSetFenbu.FieldByName('No'+inttostr(j)).asstring:=inttostr(i);
ADODataSetFenbu.post;
end
else
begin
i:=0;
end;
ADODataSetFenbu.next;
end;
end;
ADODataSetFenbu.EnableControls;
end;
var
i,j:integer;
begin
ADODataSetFenbu.DisableControls;
for j:=1 to 30 do
begin
ADODataSetFenbu.first;
i:=0;
while not ADODataSetFenbu.Eof do
begin
if ADODataSetFenbu.FieldByName('No'+inttostr(j)).asstring = '' then
begin
i:=i+1;
ADODataSetFenbu.edit;
ADODataSetFenbu.FieldByName('No'+inttostr(j)).asstring:=inttostr(i);
ADODataSetFenbu.post;
end
else
begin
i:=0;
end;
ADODataSetFenbu.next;
end;
end;
ADODataSetFenbu.EnableControls;
end;
解决方案 »
- VitualStringTree中结点文字的显示
- 为什么划线没有显示出来啊(菜鸟请教)
- 删除数据时有关外键冲突不能删除的情况,急!急!急!
- 如何控制edit里只能输入1-100的值?
- 怎么把菜单栏做成office的菜单栏风格?
- 用FindResource(DllHandle, PChar(ResName), RT_ICON) 为什么找不到资源文件?
- 怎样利用DELPHI将一文件通过HTTP上传到服务器
- 关于Query查询后编辑之问题
- 大家看见过这样的病毒吗????(很可怕的)参与者给分
- 三个问题,希望大家帮忙!
- 200分紧急求助:修改(填充)网页的内容(属性)
- delphi7 提示 is not valid integer value
//只能这样,使用一次遍历,减小29次 遍历var
i:integer;
aa : array[1..30] of byte ;
begin
FillChar( aa,30,0);
ADODataSetFenbu.DisableControls;
ADODataSetFenbu.first;
while not ADODataSetFenbu.Eof do
begin
for i:=1 to 30 do
begin
if ADODataSetFenbu.FieldByName('No'+inttostr(i)).asstring = '' then
begin
Inc(aa[i]);
ADODataSetFenbu.edit;
ADODataSetFenbu.FieldByName('No'+inttostr(i)).asstring:=aa[i];
ADODataSetFenbu.post;
end;
end;
ADODataSetFenbu.next;
end;
ADODataSetFenbu.EnableControls;
end;
而这个算法,只需 1 万次访问,记录越多,加速越快var
i:integer;
aa : array[1..30] of int64 ; //原有代码用 byte, 只支持 255 个记录
begin
for i:=1 to 30 do
array[i]=0;
ADODataSetFenbu.DisableControls;
ADODataSetFenbu.first;
while not ADODataSetFenbu.Eof do
begin
for i:=1 to 30 do
begin
if ADODataSetFenbu.FieldByName('No'+inttostr(i)).asstring = '' then
begin
Inc(aa[i]);
ADODataSetFenbu.edit;
ADODataSetFenbu.FieldByName('No'+inttostr(i)).asstring:=aa[i];
ADODataSetFenbu.post;
end;
end;
ADODataSetFenbu.next;
end;
ADODataSetFenbu.EnableControls;
end;
var
i:integer;
aa : array[1..30] of int64 ; //原有代码用 byte 有bug, 只支持 255 个记录
begin
for i:=1 to 30 do
begin
array[i]=0;
end;
ADODataSetFenbu.DisableControls;
ADODataSetFenbu.first;
while not ADODataSetFenbu.Eof do
begin
for i:=1 to 30 do
begin
if ADODataSetFenbu.FieldByName('No'+inttostr(i)).asstring = '' then
begin
Inc(aa[i]);
ADODataSetFenbu.edit;
ADODataSetFenbu.FieldByName('No'+inttostr(i)).asstring:=aa[i];
ADODataSetFenbu.post;
end
else
begin
aa[i]=0;
end;
end;
ADODataSetFenbu.next;
end;
ADODataSetFenbu.EnableControls;
end;
i:integer;
aa : array[1..30] of integer ;
begin
for i:=1 to 30 do
begin
aa[i]:=0;
end;
ADODataSetFenbu.DisableControls;
ADODataSetFenbu.first;
while not ADODataSetFenbu.Eof do
begin
for i:=1 to 30 do
begin
if ADODataSetFenbu.FieldByName('No'+inttostr(i)).asstring = '' then
begin
Inc(aa[i]);
ADODataSetFenbu.edit;
ADODataSetFenbu.FieldByName('No'+inttostr(i)).asstring:=inttostr(aa[i]);
ADODataSetFenbu.post;
end
else
begin
aa[i]:=0;
end;
end;
ADODataSetFenbu.next;
end;
ADODataSetFenbu.EnableControls;
end;
先从数据库取得数据集,记录下需要更新的行的主键,保存成一个列表,
然后分N个线程根据这个列表执行更新操作
(要用SQL语句执行更新,因为是多线程,QUERY的POST不能同时来更新多行数据)
执行完之后,再从数据库取得更新后的数据集
这样速度会快N倍,呵呵。。
先从数据库取得数据集,记录下需要更新的行的主键,保存成一个列表,
然后分N个线程根据这个列表执行更新操作
(要用SQL语句执行更新,因为是多线程,QUERY的POST不能同时来更新多行数据)
执行完之后,再从数据库取得更新后的数据集
这样速度会快N倍,呵呵。。
可以写一个存储过程,把这种数据修改后,再显示到前台界面。
我自己测试了一下,同样一个25555条的表,我更新其中一个字段
放到主线程中用了将近一分钟,分十个线程执行的话在12~15秒之间
效果显而易见PAS:
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, DB, ADODB,ActiveX,SyncObjs;const
WM_USERCOMPLETE=WM_USER+100;type
TDataUpdateThread=class(TThread)
private
FConnection:TADOConnection;
FQuery:TADOQuery;
protected
procedure Execute;override;
public
constructor Create(ASuspended:Boolean);
destructor Destroy;override;
end; TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Label1: TLabel;
Label2: TLabel;
ADOConnection1: TADOConnection;
ADOQuery1: TADOQuery;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
Complete:Boolean;
ThreadList:TList;
StartTime:TDateTime;
Lock:TRTLCriticalSection;
procedure WMUSERCOMPLETE(var message:TMessage);message WM_USERCOMPLETE;
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
begin
StartTime:=Now; ADOQuery1.First;
while Not ADOQuery1.Eof do
begin
ADOQuery1.Edit;
ADOQuery1.FieldByName('IsSpam').AsBoolean:=False;
ADOQuery1.Post;
ADOQuery1.Next;
end; Label1.Caption:='单线程:开始时间:'+DateTimeToStr(StartTime)+'结束时间:'+DateTimeToStr(Now);end;procedure TForm1.Button2Click(Sender: TObject);
var
Thread:TDataUpdateThread;
I: Integer;
begin
StartTime:=Now;
ADOQuery1.First;
//启动线程
for I := 0 to 10 - 1 do
begin
Thread:=TDataUpdateThread(ThreadList.Items[I]);
Thread.Resume;
end;
end;procedure TForm1.Button3Click(Sender: TObject);
begin
ADOQuery1.Close;
ADOQuery1.SQL.Text:='Select * from tmMailList1';
ADOQuery1.Open;
end;procedure TForm1.FormCreate(Sender: TObject);
var
Thread:TDataUpdateThread;
I: Integer;
begin
InitializeCriticalSection(Lock);
Complete:=False; ADOQuery1.Close;
ADOQuery1.SQL.Text:='Select * from tmMailList1';
ADOQuery1.Open; //创建线程
ThreadList:=TList.Create;
for I := 0 to 10 - 1 do
begin
Thread:=TDataUpdateThread.Create(True);
ThreadList.Add(Thread)
end;
end;procedure TForm1.FormDestroy(Sender: TObject);
begin
DeleteCriticalSection(Lock);
end;procedure TForm1.WMUSERCOMPLETE(var message: TMessage);
begin
ADOQuery1.Close;
ADOQuery1.Open;
Label2.Caption:='多线程:开始时间:'+DateTimeToStr(StartTime)+'结束时间:'+DateTimeToStr(Now);
end;{ TDataUpdateThread }constructor TDataUpdateThread.Create(ASuspended: Boolean);
begin
Inherited Create(ASuspended); FConnection:=TADOConnection.Create(nil);
FConnection.ConnectionString:='False';
FConnection.Connected:=True;
FQuery:=TADOQuery.Create(nil);
FQuery.Connection:=FConnection;end;destructor TDataUpdateThread.Destroy;
begin
FConnection.Free;
FQuery.Free;
inherited;
end;procedure TDataUpdateThread.Execute;
var
FID:Integer;
First:Boolean;
begin
inherited;
First:=False;
while Not Terminated do
begin
while Not Form1.ADOQuery1.Eof do
begin EnterCriticalSection(Form1.Lock);
if Not Form1.ADOQuery1.Eof then
begin
FID:=Form1.ADOQuery1.FieldByName('MID').AsInteger;
Form1.ADOQuery1.Next;
end
else
begin
if Not Form1.Complete then
begin
First:=True;
Form1.Complete:=True;
end;
end;
LeaveCriticalSection(Form1.Lock);
if Not Form1.Complete then
begin
FQuery.Close;
FQuery.SQL.Text:='Update tmMailList1 set IsSpam=0 where MID='+IntToStr(FID);
FQuery.ExecSQL;
end; if First then
begin
PostMessage(Form1.Handle,WM_USERCOMPLETE,0,0);
end; if Form1.Complete then
begin
Terminate;
end;
end;
end;
end;initialization
CoInitialize(nil);finalization
CoUnInitialize;end.
DFM:object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 263
ClientWidth = 483
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
OnDestroy = FormDestroy
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 24
Top = 143
Width = 385
Height = 13
AutoSize = False
Caption = 'Label1'
end
object Label2: TLabel
Left = 24
Top = 184
Width = 385
Height = 13
AutoSize = False
Caption = 'Label1'
end
object Button1: TButton
Left = 72
Top = 112
Width = 75
Height = 25
Caption = #21333#32447#31243#22788#29702
TabOrder = 0
OnClick = Button1Click
end
object Button2: TButton
Left = 288
Top = 112
Width = 75
Height = 25
Caption = #22810#32447#31243#22788#29702
TabOrder = 1
OnClick = Button2Click
end
object Button3: TButton
Left = 200
Top = 32
Width = 75
Height = 25
Caption = 'Button3'
TabOrder = 2
OnClick = Button3Click
end
object ADOConnection1: TADOConnection
Connected = False
LoginPrompt = False
Provider = 'SQLOLEDB.1'
Left = 96
Top = 24
end
object ADOQuery1: TADOQuery
Connection = ADOConnection1
Parameters = <>
Left = 96
Top = 64
end
end呵呵,贴上代码,随便写写。。高手请匆挑错啊。。
开二十个线程也试了一下,也差不多十几秒。。线程数自己衡量吧。