Прервать SQL-запрос с ограничением времени обработки

Могу ли я писать SQL-запросы, используя компоненты DELPHI, dbgo DB и сервер базы данных SQL Server, которые ограничены по времени обработки?

Нравится

select * from table where ......  

и process_time_limit = 5 sec ?

Лучше вы дадите мне 10% строк в течение срока, вместо того, чтобы ждать часами для полного набора данных запроса


person Franz    schedule 03.02.2013    source источник
comment
Что вы хотите, чтобы произошло, когда 5 секунд были достигнуты? Исключение, которое вы можете обработать, или что-то еще? И какую версию вы используете (может быть, здесь вам поможет Resource Governor).   -  person Aaron Bertrand    schedule 03.02.2013
comment
Также см. stackoverflow.com/questions/5077051/ - CommandTimeout может помочь, но это может зависеть от пары других факторов.   -  person Aaron Bertrand    schedule 03.02.2013
comment
Возможно, вам следует избегать запуска запросов, выполнение которых занимает несколько часов.   -  person Ondrej Kelle    schedule 03.02.2013
comment
@TOndrej: иногда вам просто нужна эта информация :-)   -  person Marjan Venema    schedule 04.02.2013
comment
@MarjanVenema В таких случаях должна быть возможность оптимизировать базу данных, чтобы запросы не занимали так много времени.   -  person Ondrej Kelle    schedule 04.02.2013
comment
@TOndrej: Да, я не спорю с твоей точкой зрения. Однако, когда вам нужно просмотреть 200 или даже 20 ГБ данных, чтобы получить нужную информацию, это просто займет время, независимо от того, насколько оптимизирована ваша база данных и/или запрос. Возможно, вы могли бы разделить запрос на более мелкие, но несколько запросов с временными результатами могут просто скрыть (и увеличить) общее время, необходимое для получения ответа.   -  person Marjan Venema    schedule 04.02.2013


Ответы (1)


Компоненты ADO:

Я бы попробовал асинхронную выборку данных. Когда вы будете выполнять запрос, вы будете помнить, когда вы начали, и каждый раз, когда OnFetchProgress срабатывает, вы проверяете, находится ли EventStatus все еще находится в состоянии esOK и проверьте время, прошедшее с момента выполнения запроса. Если он истек, вы можете отменить выборку данных с помощью Cancel в вашем наборе данных.

Я хотел использовать что-то вроде следующего (непроверенного) псевдокода:

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;
person TLama    schedule 03.02.2013
comment
Хм, документ для Cancel говорит: Отменяет изменения активной записи, если эти изменения еще не опубликованы. Вы уверены, что здесь это сработает по прямому назначению - отменить следующую выборку? - person ain; 03.02.2013
comment
Спасибо за то, что поделились этой идеей, я попробую - person Franz; 04.02.2013