Конференция "Базы" » Запрос на выборку [D7, access]
 
  • Fedor (21.05.09 16:48) [0]
    Как при помощи sql запроса отображать только то количество записей, которое убирается в область отображения DBGrid? Например пусть DBGrid может отображать 10 записей.
  • Sergey13 © (21.05.09 16:58) [1]
    Иди от обратного - запрашивай ТОЛЬКО те данные, которые нужны пользователю СЕЙЧАС.
  • Ega23 © (21.05.09 17:05) [2]

    > Как при помощи sql запроса отображать только то количество
    > записей, которое убирается в область отображения DBGrid?
    >  Например пусть DBGrid может отображать 10 записей.


    Тут такая штука. У тебя на экране DBGrid отображает 10 записей. Потом ты окошко на весь экран развернул - и он начал отображать уже 40 записей. Потом поменял разрешение экрана - и уже 28 записей.
    На каждый такой раз "стрелять" в базу запросом... Ну не знаю. ИМХО, непродуктивно.

    Ты лучше задачу в целом опиши. Какие есть исходные данные, и что бы ты конкретно хотел бы получить. Тут народ опытный, может чего интересного посоветуют.
  • Fedor (21.05.09 17:12) [3]
    А пользователю и нужны те записи что отображены в гриде. Кроме того он еще и скролирует его. На вскидку, я думаю так: мы отображаем первые 10 записей.
    select top 10 * from table order by id.
    Затем пользователь начинает "бегать" по гриду изменяя позицию.
    Когда он попадает на последнюю запись в гриде мы выполняем запрос типа:
    select top 10 * from table where id>=:id order by id.
    Пользователь в гриде получит следующие 10 записей с текущей.
    Так же можно сделать и при переходе на первую запись в гриде:
    select top 10 * from table where id<=:id order by id.
    Где параметр :id - id текущей записи.

    Возможно так.
  • Fedor (21.05.09 17:18) [4]

    > Тут такая штука. У тебя на экране DBGrid отображает 10 записей.
    >  Потом ты окошко на весь экран развернул - и он начал отображать
    > уже 40 записей. Потом поменял разрешение экрана - и уже
    > 28 записей.На каждый такой раз "стрелять" в базу запросом.
    > .. Ну не знаю. ИМХО, непродуктивно.Ты лучше задачу в целом
    > опиши. Какие есть исходные данные, и что бы ты конкретно
    > хотел бы получить. Тут народ опытный, может чего интересного
    > посоветуют.


    Пусть размер грида жесткий на 10 записей. В базе порядка 500 основных записей с фотками, плюс к каждой из в присоединенной таблице по несколько сотен записей. Сейчас вес базы около 40 мегов. А отображать нужно сразу все включая графику Chart по детальным таблицам.
    Просто думаю если отображать главную таблицу частями быстрее будет.
  • Виталий Панасенко (21.05.09 17:21) [5]

    > Просто думаю если отображать главную таблицу частями быстрее
    > будет.

    А овчинка вычинки стоит?
  • Ega23 © (21.05.09 17:29) [6]

    > Просто думаю если отображать главную таблицу частями быстрее
    > будет.


    Нет. Ты отображай детали только по текущей записи. Т.е. когда ты в гриде перешёл на новую запись - отрабатывает маленький подзапрос, который вытаскивает только то, что принадлежит ей.
    Короче, как пример.

    Create MasterTable (MID int, MName varchar(32))
    Insert into MasterTable (MID, MName) Values (1, 'M1');
    ....
    Insert into MasterTable (MID, MName) Values (10, 'M10');

    Create DetailTable (DID, MID (ключ на Master), Name)
    Insert into DetailTable (DID, MID, Name) Values (1, 1, 'D11');
    Insert into DetailTable (DID, MID, Name) Values (2, 1, 'D12');
    ....
    Insert into DetailTable (DID, MID, Name) Values (10, 1, 'D110');
    Insert into DetailTable (DID, MID, Name) Values (11, 2, 'D21');
    ....
    Insert into DetailTable (DID, MID, Name) Values (100, 10, 'D1010');

    Итого: в мастере - 10 записей, для каждой записи в мастере - 10 записей в детали.

    Кладём 2 грида, 2 DataSet, 2 DataSource и настраиваем Master-Detail связку (об этом в книге почитай).
    Получается, что в один момент времени загружено всего 20 записей: 10 в мастере, и 10 в детали, которая соответствует текущему значению Мастера.

    Как-то так.
  • Медвежонок Пятачок © (21.05.09 17:31) [7]
    Возможно так.

    Оно и так уже "так"
    В запрос может попасть тысяча записей.
    Если он привязан к гриду, то фетч идет до тех пор, пока не кончится место в его клиентской части.
  • Fedor (21.05.09 17:31) [8]
    Эксперемент. Будет прирост скорости - очень хорошо. Есть конечно подозрение, что лишние запросы при навигации съедят все увеличение скорости работы.
  • Медвежонок Пятачок © (21.05.09 17:32) [9]
    если вообще будет что съедать
  • sniknik © (21.05.09 17:55) [10]
    > Просто думаю если отображать главную таблицу частями быстрее будет.
    будет медленнее.

    > В запрос может попасть тысяча записей.
    > Если он привязан к гриду, то фетч идет до тех пор, пока не кончится место в его клиентской части.
    1000 записей выбирается за 0,01 секунды максимум. одна отрисовка формы с гридом гораздо существеннее по времени.
    и фетч при локальном курсоре отбирает все.

    > Есть конечно подозрение, что лишние запросы при навигации съедят все увеличение скорости работы.
    есть подозрения, что твои "тормоза" не имеют ничего общего с теми, что ты ищешь...
  • Ega23 © (21.05.09 17:55) [11]

    > Если он привязан к гриду, то фетч идет до тех пор, пока
    > не кончится место в его клиентской части.


    Я бы не стал заходить так далеко и выражаться столь категорично. Всё от конкретной реализации TDataSet зависит.
  • Fedor (22.05.09 09:24) [12]

    > есть подозрения, что твои "тормоза" не имеют ничего общего
    > с теми, что ты ищешь...


    Возможно. Опишу проблему.
    Поиск организован следующим образом:

    procedure TForm1.Edit2Change(Sender: TObject);
    begin
     if Edit2.Text<>'' then
       begin
         CustDS.Close;
         CustDS.CommandText:='select * from customers where surname like "'+Edit2.Text+'%" order by card';
         CustDS.Open;
       end
       else
       begin
         CustDS.Close;
         CustDS.CommandText:='select * from customers order by card';
         CustDS.Open;
       end;
    end;

    Когда мы вводим текст в поле Edit все работает замечательно. Но стоит очистить поле база замирает выполняя запрос

    select * from customers order by card

    На слабых машина прога виснет. На моем ноуте Core2Duo с 4 гигами задержка примерно секунды 3. Количество записей около 500 записей с фотками. Может так быть должно?
  • Медвежонок Пятачок © (22.05.09 09:27) [13]
    ты посчитай сколько раз при этом вызывается onchange
  • MsGuns © (22.05.09 09:29) [14]
    >Fedor   (21.05.09 17:12) [3]
    >А пользователю и нужны те записи что отображены в гриде. Кроме того он еще и скролирует его. >На вскидку, я думаю так: мы отображаем первые 10 записей.
    >Затем пользователь начинает "бегать" по гриду изменяя позицию.
    >Когда он попадает на последнюю запись в гриде мы выполняем запрос типа:

    Эта.. вот собрались друзья отметить событие, сбегали в лавку, купили чекушку. Дернули - сбегали еще раз в лавку - купили по огурцу, закусили. Затем опять сбегали за новой чекушкой, дернули. Сбегали за 100 гр. колбаски - закусили.
    И т.д.
  • Медвежонок Пятачок © (22.05.09 09:36) [15]
    >Когда он попадает на последнюю запись в гриде мы выполняем запрос типа:

    Предварительно промедитировав куда именно в будущем направится юзер с этой записи. Вверх или вниз. Или вообще никуда не направится, а закроет программу через 10 секунд.
  • Fedor (22.05.09 09:40) [16]

    > ты посчитай сколько раз при этом вызывается onchange


    Два раза. Например мы ввели символ "а" - у нас список фамилий на "а". Нажали "Backspace" - у нас таблица полностью.
  • Сергей М. © (22.05.09 09:44) [17]

    > Fedor   (22.05.09 09:24) [12]


    1. У тебя поле card индексировано ?
    2. Курсор НД на клиентской или серверной стороне ?
    3. Так ли уж необходим инкрементальный поиск/выборка ?
  • Fedor (22.05.09 09:51) [18]

    > 1. У тебя поле card индексировано ?


    Да. На уровне создания базы.
    Вот в DataSet это не отмечено.


    > 2. Курсор НД на клиентской или серверной стороне ?


    Клиент.


    > 3. Так ли уж необходим инкрементальный поиск/выборка ?


    Очень нужен.
  • Ega23 © (22.05.09 09:55) [19]

    > Очень нужен.


    А зачем на OnChange вешать? Положи рядом кнопочку "Обновить".
    Да, и если уж на то пошло, то:
    procedure TForm1.Edit2Change(Sender: TObject);
    begin
     with CustDS do
     begin
       Close;
       if (Edit2.text = '') then
          CommandText := ....
       else
          CommandText := ....;

       try
         Open;
       except
          .....
       end;
     end;

 
Конференция "Базы" » Запрос на выборку [D7, access]
Есть новые Нет новых   [134473   +31][b:0][p:0.001]