Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2010.08.27;
Скачать: CL | DM;

Вниз

Запрос на выборку   Найти похожие ветки 

 
Fedor   (2009-05-21 16:48) [0]

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


 
Sergey13 ©   (2009-05-21 16:58) [1]

Иди от обратного - запрашивай ТОЛЬКО те данные, которые нужны пользователю СЕЙЧАС.


 
Ega23 ©   (2009-05-21 17:05) [2]


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


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

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


 
Fedor   (2009-05-21 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   (2009-05-21 17:18) [4]


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


Пусть размер грида жесткий на 10 записей. В базе порядка 500 основных записей с фотками, плюс к каждой из в присоединенной таблице по несколько сотен записей. Сейчас вес базы около 40 мегов. А отображать нужно сразу все включая графику Chart по детальным таблицам.
Просто думаю если отображать главную таблицу частями быстрее будет.


 
Виталий Панасенко   (2009-05-21 17:21) [5]


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

А овчинка вычинки стоит?


 
Ega23 ©   (2009-05-21 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 в детали, которая соответствует текущему значению Мастера.

Как-то так.


 
Медвежонок Пятачок ©   (2009-05-21 17:31) [7]

Возможно так.

Оно и так уже "так"
В запрос может попасть тысяча записей.
Если он привязан к гриду, то фетч идет до тех пор, пока не кончится место в его клиентской части.


 
Fedor   (2009-05-21 17:31) [8]

Эксперемент. Будет прирост скорости - очень хорошо. Есть конечно подозрение, что лишние запросы при навигации съедят все увеличение скорости работы.


 
Медвежонок Пятачок ©   (2009-05-21 17:32) [9]

если вообще будет что съедать


 
sniknik ©   (2009-05-21 17:55) [10]

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

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

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


 
Ega23 ©   (2009-05-21 17:55) [11]


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


Я бы не стал заходить так далеко и выражаться столь категорично. Всё от конкретной реализации TDataSet зависит.


 
Fedor   (2009-05-22 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 записей с фотками. Может так быть должно?


 
Медвежонок Пятачок ©   (2009-05-22 09:27) [13]

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


 
MsGuns ©   (2009-05-22 09:29) [14]

>Fedor   (21.05.09 17:12) [3]
>А пользователю и нужны те записи что отображены в гриде. Кроме того он еще и скролирует его. >На вскидку, я думаю так: мы отображаем первые 10 записей.
>Затем пользователь начинает "бегать" по гриду изменяя позицию.
>Когда он попадает на последнюю запись в гриде мы выполняем запрос типа:

Эта.. вот собрались друзья отметить событие, сбегали в лавку, купили чекушку. Дернули - сбегали еще раз в лавку - купили по огурцу, закусили. Затем опять сбегали за новой чекушкой, дернули. Сбегали за 100 гр. колбаски - закусили.
И т.д.


 
Медвежонок Пятачок ©   (2009-05-22 09:36) [15]

>Когда он попадает на последнюю запись в гриде мы выполняем запрос типа:

Предварительно промедитировав куда именно в будущем направится юзер с этой записи. Вверх или вниз. Или вообще никуда не направится, а закроет программу через 10 секунд.


 
Fedor   (2009-05-22 09:40) [16]


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


Два раза. Например мы ввели символ "а" - у нас список фамилий на "а". Нажали "Backspace" - у нас таблица полностью.


 
Сергей М. ©   (2009-05-22 09:44) [17]


> Fedor   (22.05.09 09:24) [12]


1. У тебя поле card индексировано ?
2. Курсор НД на клиентской или серверной стороне ?
3. Так ли уж необходим инкрементальный поиск/выборка ?


 
Fedor   (2009-05-22 09:51) [18]


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


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


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


Клиент.


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


Очень нужен.


 
Ega23 ©   (2009-05-22 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;


 
Виталий Панасенко   (2009-05-22 09:58) [20]

А почему фотки не показывать отдельно? точнее, фетчить? бегай себе по гриду, нужно показать всю инфу(фото) - выборка ОДНОЙ ЗАПИСИ для показа


 
Сергей М. ©   (2009-05-22 10:27) [21]


> в DataSet это не отмечено


Что значит "не отмечено" ?


 
MsGuns ©   (2009-05-22 10:58) [22]

>На слабых машина прога виснет. На моем ноуте Core2Duo с 4 гигами задержка примерно >секунды 3. Количество записей около 500 записей с фотками.

Во как !
Решение в [20] - т.е. извлекаются все поля, которые можно внятно (т.е. текстом) показать в сетке. А для фоток кнопульку, по нажатию на которую с сервера тянется блоб (блобы) ТОЛЬКО ПО ТЕКУЩЕЙ ЗАПИСИ. Ну примерно так, как это показано в фильмах, где смотрят разные досье


 
Медвежонок Пятачок ©   (2009-05-22 11:18) [23]

Два раза. Например мы ввели символ "а" - у нас список фамилий на "а". Нажали "Backspace" - у нас таблица полностью.

Например он сначала ввел "ля-ля-тополя", а потом притопил backspace


 
sniknik ©   (2009-05-22 11:51) [24]

> Но стоит очистить поле база замирает выполняя запрос
на выборке без условий, т.е. 500 записей? смешно. где то еще есть неучтенные тормоза, может у тебя какие то события привязаны к датасету.
проверь свой полный запрос в независимой проге, например -
http://webfile.ru/3635677
тоже 3 сек?

и потом, если есть выборка полностью то частичная она как бы уже лишняя, отбор произошел, смысла перезапрашивать нет, можно делать просто фильтром по выбранному.


 
Игорь Шевченко ©   (2009-05-22 11:58) [25]


> 1000 записей выбирается за 0,01 секунды максимум


Это смотря какой запрос


 
sniknik ©   (2009-05-22 12:04) [26]

> Это смотря какой запрос
в accecc особо сложных не бывает.

тем более здесь уже явно указан
> CustDS.CommandText:="select * from customers order by card";
выполняется 3 сек на Core2Duo с 4 гигами.

очевидно что то не так.


 
Нат   (2009-05-23 00:56) [27]

1. Зачем в гриде поле с фоткой?
Все равно толком не отобразить.
Для фотки сделать отдельный запрос и датасет.
2. ADODataSet сам (внутри себя) реализует то, что Вы пытаетесь сделать.
Для этого есть свойства CacheSize, BlockReadSize  и MaxRecords и событие OnEndOfRecordSet


 
sniknik ©   (2009-05-23 13:09) [28]

> Для фотки сделать отдельный запрос и датасет.
зачем? блоб поля и так не включаются в датасет, и скачиваются с сервера только при обращении т.е. тут при отрисовке.

> 2. ADODataSet сам (внутри себя) реализует то, что Вы пытаетесь сделать.
не совсем, есть похожий режим но это не то что хочет автор.
он хочет скачать 10 и показывать их пока страницу не перелистнут тогда скачать следующие 10 и т.д., т.е. делается скачка и показ кусками.
а то про что ты говоришь, это способ построения рекордсета, т.е. там скачивается на размер блока и сразу после этого рекордсет становится активным, данные отображаются но скачка не останавливается а продолжается в фоне пока не сформируется весь, неважно перелистнут страницу или нет.
разница однако.
скорее к тому что он хочет ближе серверный курсор, но и он работает не совсем так, не блоками, а по обращению непосредственно к записям. если смотреть только на листание то оно будет один в один как хочет. но без толку, т.к. проблема не в способе запросов. этим только "замылит" настоящую проблему (ну вот представим что на получение записи стоит какая то обработка и тормоз от нее, при локальном курсоре она прогоняется 500раз при открытии и тормоза заметны, при серверном будет только 10 (сколько получили для отображения грида), незаметно хотя проблемная обработка никуда не делась, т.е. тормоза сейчас сконцентрированные в одном месте просто "размажутся" по всему времени работы с датасетом, но стоит например сделать по нему цикл... все начнется заново.).


 
Нат ©   (2009-05-24 04:06) [29]

Да, проблема не локализована.
По поводу ускорения.
1. Преступно формировать запрос "select ..." + Edit2.Text
Можно гарантировать, что в едите не всегда будут правильные данные.
2. Вы похоже обрабатываете запрос на ввод каждого символа.
Может быть стоит ужесточить условия отбора вводом как минимум 2..3-х символов. Кроме того, стоит проверять на пустоту едита.
Т.о. сначала присваиваете в переменную, если имеется пустое значение, подставляйте что-нибудь, что не позволит вывести все записи.
3. В большинстве случаев можно явно указать требуемые поля.
Выводите не все, а минимум, необходимый в гриде.
Для подробных сведений, делайте Детайл - все поля будете выводить только для одной записи.
Например.
If lenght(Edit2.Text) <3 then TextVal := "Ключ к записи, которая выводится по умолчанию"
else  TextVal := Edit2.Text;
"select id, tel, adr, director ..." + TextVal + "%";
Таким образом, вы будете перекачивать по сети на порядок меньше информации.


 
Нат ©   (2009-05-24 04:14) [30]

Поправлю
If lenght(Edit2.Text) <3 then TextVal := "Ключ к записи, которая выводится по умолчанию"
else  TextVal := Edit2.Text + "%";
"select id, tel, adr, director ..." + TextVal ;
Добавлять впереди "%" - нет смысла, это ограничит возможности.
Без первого "%" поиск осуществляется с начала строки.
Если пользователь желает, он сам добавит "%" в эдит, и поиск пойдет по вхождению подстроки с любого места.



Страницы: 1 вся ветка

Текущий архив: 2010.08.27;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 2.608 c
8-1204709161
IGray
2008-03-05 12:26
2010.08.27
Как создать объект DirectDraw на втором мониторе?


15-1271226541
paxpet
2010-04-14 10:29
2010.08.27
Может кто-нибудь знает что происходит


15-1267433491
Prizrak
2010-03-01 11:51
2010.08.27
Delphi утилита для извлечения функций из любой dll


15-1275547795
Sergey Masloff
2010-06-03 10:49
2010.08.27
Электронные книжки - что купить


15-1264381741
Кто б сомневался
2010-01-25 04:09
2010.08.27
Пайкерит (прочный материал)