热门(对不起)答案,对于那些没有时间进入但可能有类似问题的人。
规则#1一如既往地尽可能地从循环中移动 2,移动TField var:= ADODataSet.FieldByname()退出循环 3,ADODataSet.DisableControls();和ADODataSet.EnableControls();围绕循环 4,stringGrid.Rows [r] .BeginUpdate()和EndUpdate()在每一行(不能做的控制) 每一个都刮掉了几秒钟,但是我把它变成了“比眼睛看得更快”通过改变
loop
stringGrid.RowCount := stringGrid.RowCount + 1;
end loop
将stringGrid.RowCount := ADODataSet.RecordCount;
放在循环
+1并衷心感谢所有帮助过的人。
(现在我将去看看我能做些什么来优化绘制TChart,这也很慢; - )
表中有大约3,600行,这需要45秒来填充字符串网格。我做错了什么?
ADODataSet := TADODataSet.Create(Nil); ADODataSet.Connection := AdoConnection; ADODataSet.CommandText := 'SELECT * FROM measurements'; ADODataSet.CommandType := cmdText; ADODataSet.Open(); while not ADODataSet.eof do begin TestRunDataStringGrid.RowCount := TestRunDataStringGrid.RowCount + 1; measurementDateTime := UnixToDateTime(ADODataSet.FieldByname('time_stamp').AsInteger); DoSQlCommandWithResultSet('SELECT * FROM start_time_stamp', AdoConnection, resultSet); startDateTime := UnixToDateTime(StrToInt64(resultSet.Strings[0])); elapsedTime := measurementDateTime - startDateTime; TestRunDataStringGrid.Cells[0, Pred(TestRunDataStringGrid.RowCount)] := FormatDateTime('hh:mm:ss', elapsedTime); TestRunDataStringGrid.Cells[1, Pred(TestRunDataStringGrid.RowCount)] := FloatToStrWithPrecision(ADODataSet.FieldByname('inputTemperature').AsFloat); TestRunDataStringGrid.Cells[2, Pred(TestRunDataStringGrid.RowCount)] := FloatToStrWithPrecision(ADODataSet.FieldByname('outputTemperature').AsFloat); TestRunDataStringGrid.Cells[3, Pred(TestRunDataStringGrid.RowCount)] := FloatToStrWithPrecision(ADODataSet.FieldByname('flowRate').AsFloat); TestRunDataStringGrid.Cells[4, Pred(TestRunDataStringGrid.RowCount)] := FloatToStrWithPrecision(ADODataSet.FieldByname('waterPressure').AsFloat * convert); TestRunDataStringGrid.Cells[5, Pred(TestRunDataStringGrid.RowCount)] := FloatToStrWithPrecision(ADODataSet.FieldByname('waterLevel').AsFloat); TestRunDataStringGrid.Cells[6, Pred(TestRunDataStringGrid.RowCount)] := FloatToStrWithPrecision(ADODataSet.FieldByname('cod').AsFloat); ADODataSet.Next; end; ADODataSet.Close(); ADODataSet.Free();
更新
Function DoSQlCommandWithResultSet(const command : String; AdoConnection : TADOConnection; resultSet : TStringList): Boolean; var i : Integer; AdoQuery : TADOQuery; begin Result := True; resultSet.Clear(); AdoQuery := TADOQuery.Create(nil); try AdoQuery.Connection := AdoConnection; AdoQuery.SQL.Add(command); AdoQuery.Open(); i := 0; while not AdoQuery.eof do begin resultSet.Add(ADOQuery.Fields[i].Value); i := i + 1; AdoQuery.Next; end; finally AdoQuery.Close(); AdoQuery.Free(); end; end;
答案 0 :(得分:10)
您正在执行命令SELECT * FROM start_time_stamp
3,600次,但在我看来它并不以任何方式与您的外循环相关联。为什么不在循环之前执行一次?
SELECT命令似乎只返回单个记录的单个列,但是您使用“*”来加载所有列,而没有WHERE子句将结果限制为单个行(如果有多个表中的一行)。
您只使用测量中的有限数量的列,但使用“*”检索所有列。
您没有显示DoSQlCommandWithResultSet
的内容,因此不清楚该例程是否存在问题。
目前尚不清楚问题是在您的数据库访问还是字符串网格中。注释掉与字符串网格相关的所有行并运行程序。单独访问数据库需要多长时间?
答案 1 :(得分:9)
除了Larry Lustig点:
InputTempField := ADODataSet.FieldByname('inputTemperature');
TestRunDataStringGrid.RowCount := TestRunDataStringGrid.RowCount + 1
中调整网格大小。如果你应该在循环之前使用ADODataSet.RecordCount
:TestRunDataStringGrid.RowCount := ADODataSet.RecordCount
。ADODataSet.DisableControls
并在循环之后调用ADODataSet.EnableControls
是一个好习惯。更实际的是ADO数据集,它没有最佳实现,而且这些调用有帮助。答案 2 :(得分:5)
而不是在循环内调用ADODataSet.FieldByname('Fieldname'),你应该为每个字段声明TField类型的局部变量,将ADODataset.FindField('Fieldname')分配给变量并使用循环内的变量。 FindFieldByName会在每次调用时搜索列表。
更新
procedure TForm1.Button1Click(Sender: TObject);
var
InputTemp, OutputTemp: TField;
begin
ADODataSet := TADODataSet.Create(Nil);
try
ADODataSet.Connection := ADOConnection;
ADODataSet.CommandText := 'SELECT * FROM measurements';
ADODataSet.Open;
InputTemp := ADODataSet.FindField('inputTemperature');
OutputTemp := ADODataSet.FindField('outputTemperature');
// assign more fields here
while not ADODataSet.Eof do begin
// do something with the fields, for example:
// GridCell := Format ('%3.2f', [InputTemp.AsFloat]);
// GridCell := InputTemp.AsString;
ADODataSet.Next;
end;
finally
ADODataSet.Free;
end;
end;
另一种选择是在表单上删除TADODataset Componont(或使用TDataModule)并在设计时定义字段。
答案 3 :(得分:2)
除了Larry Lustig的回答之外,请考虑使用data-aware
控件,例如 TDbGrid
组件。
答案 4 :(得分:2)
如果您没有使用数据感知控件,则应在循环之前使用TestRunDataStringGrid.BeginUpdate
并在循环之后使用TestRunDataStringGrid.EndUpdate
。如果没有这个,你的网格会在每次修改后不断重绘(添加新行,单元格更新)。
在打开查询之前,另一个提示设置为AdoQuery.LockType := ltReadOnly
。
答案 5 :(得分:1)
您还可以尝试使用仪器分析器而不是采样分析器来获得更好的结果(采样分析器会错过很多细节信息,而且大多数时候它们每秒的样本少于1000个样本,1000个样本已经很低了:只有很好才能获得快速概述)。
检测分析器: