6

Can I write SQL queries using DELPHI, dbgo DB components and a SQL Server database server which are limited in respect to the process time ?

Like

select * from table where ......  

and process_time_limit = 5 sec ?

Better you give me 10% of the rows within a time limit instead of waiting hours for the complete query dataset

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Franz
  • 1,883
  • 26
  • 47
  • What do you want to happen when 5 seconds has been reached? An exception that you can handle, or something else? And what edition are you using (maybe Resource Governor can help here). – Aaron Bertrand Feb 03 '13 at 17:24
  • Also see http://stackoverflow.com/questions/5077051/ado-components-commandtimeout - `CommandTimeout` may help but it may depend on a couple of other factors. – Aaron Bertrand Feb 03 '13 at 17:28
  • 3
    Maybe you should avoid starting queries which take hours to complete. – Ondrej Kelle Feb 03 '13 at 17:52
  • @TOndrej: sometimes you just need that information :-) – Marjan Venema Feb 04 '13 at 06:37
  • @MarjanVenema In such cases it should be possible to optimize the database so the queries don't take that long. – Ondrej Kelle Feb 04 '13 at 08:59
  • 1
    @TOndrej: Yes, I am not arguing against your point. However, when you need to traverse 200 or even 20 GB of data to get the information you need, it is just going to take time no matter how optimized your database and/or query is. Maybe you could split the query into smaller ones, but multiple queries with temporary results may just "hide" (and increase) the total time needed to get the answer. – Marjan Venema Feb 04 '13 at 09:11

1 Answers1

3

ADO components:

I would give a try to the asynchronous data fetch. When you'd execute the query, you'll remember when you've started and every time the OnFetchProgress event fires, you'll check if the EventStatus is still in esOK state and check the time elapsed from the query execution. If it elapsed, you might cancel data fetch by using the Cancel method on your dataset.

I meant to use something like the following (untested) pseudocode:

var
  FQueryStart: DWORD;

procedure TForm1.FormCreate(Sender: TObject);
begin
  // configure the asynchronous data fetch for dataset
  ADOQuery1.ExecuteOptions := [eoAsyncExecute, eoAsyncFetchNonBlocking];
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  // store the query execution starting time and execute a query
  FQueryStart := GetTickCount;
  ADOQuery1.SQL.Text := 'SELECT * FROM Table';
  ADOQuery1.Open;
end;

procedure TForm1.ADOQuery1FetchProgress(DataSet: TCustomADODataSet; Progress,
  MaxProgress: Integer; var EventStatus: TEventStatus);
begin
  // if the fetch progress is in esOK (adStatusOK) status and the time since
  // the query has been executed (5000 ms) elapsed, cancel the query
  if (EventStatus = esOK) and (GetTickCount - FQueryStart >= 5000) then
    DataSet.Cancel;
end;
TLama
  • 75,147
  • 17
  • 214
  • 392
  • Hmm, the doc for the `Cancel` says: "Cancels modifications to the active record if those changes are not yet posted." Are you sure it would work for the intended purpose here - to cancel the next fetch? – ain Feb 03 '13 at 16:38
  • 1
    Thanks on this idea sharing, I 'll have atry on it – Franz Feb 03 '13 at 20:59