Небольшой вопрос по поводу баз данных с fcl-db
Модератор: Модераторы
Небольшой вопрос по поводу баз данных с fcl-db
Когда получаешь данные с TQuery, TSQLConnection и прочими, вот в экземпляре TQuery вызываешь метод Next. Вопрос вот в чём: при этом все данные получаются все сразу, и я потом только их перебираю, или же они получаются некими порциями, по одной штуке, скажем, а потом освобождаются?
То есть, если у меня в таблице 1000000000...... записей, я их запрошу и начну перебирать, то они все сразу придут и будут все в памяти висеть пока не закроешь query, или они будут по частям приходить, и уже просмотренные будут освобождаться?
То есть, если у меня в таблице 1000000000...... записей, я их запрошу и начну перебирать, то они все сразу придут и будут все в памяти висеть пока не закроешь query, или они будут по частям приходить, и уже просмотренные будут освобождаться?
Я не смотрел именно TSQLQuery (только TZQuery из Zeoslib), но записи должны приходить частями. Сколько записей в одной части задается в TZQuery настройкой FetchRow. Аналогичная настройка должна быть и в TSQLQuery и похоже это PacketRecords.
Просмотренные записи не освобождаются.
Просмотренные записи не освобождаются.
Получается как-то немного тупо. Когда в Query перебираешь полученные записи методом Next, то предыдущие уже просмотренные должны освобождаться, к ним же всё равно нельзя вернуться, метода Back или Previous нету
Prior не оно ?
Данные загружаются порциями (можно и все сразу) и остаются до... того времени пока они Вам не нужны. Как то так. По крайней мере - основы SQl вроде как...
скоко лет уже этому и вроде никто не жаловался...Получается как-то немного тупо
Данные загружаются порциями (можно и все сразу) и остаются до... того времени пока они Вам не нужны. Как то так. По крайней мере - основы SQl вроде как...
Я вот что имею в виду:::
Вот в этом примере результат загружается в переменную a, потом она затирается....
Если я таким образом буду просматривать триллиард записей, то это будет долго, но с памятью проблем быть не должно, так как предыдущие результаты я не храню. Вопрос в том, хранятся ли они где-то на уровне fcl-db? Я не храню предыдущие a, но я не знаю, хранятся ли они где-то в реализации класса TQuery или вообще по логике модулей fcl-db. Надеюсь стало понятно что я имею в виду.
В случае если предыдущие записи не хранятся, то просмотр записей с отбрасыванием предыдущих результатов сработает. В случае же если предыдущие записи хранятся,,, то не смотря на то что в _моём_ коде они не хранятся _явно_, памяти при большом количестве записей может не хватить, ок да.....
Добавлено спустя 1 минуту 42 секунды:
я имею в виду fcl-db предыдущие записи хранит или нет. Понятно по крайней мере что все записи сразу не загружаются. Они загружаются постепенно. Вопрос в том, освобождаются ли они постепенно
Код: Выделить всё
var
q: TQuery;
begin
...
a := q.FieldByName("a").AsString;
q.Next;
a := q.FieldByName("a").AsString;
q.Next;
a := q.FieldByName("a").AsString;
...
Вот в этом примере результат загружается в переменную a, потом она затирается....
Если я таким образом буду просматривать триллиард записей, то это будет долго, но с памятью проблем быть не должно, так как предыдущие результаты я не храню. Вопрос в том, хранятся ли они где-то на уровне fcl-db? Я не храню предыдущие a, но я не знаю, хранятся ли они где-то в реализации класса TQuery или вообще по логике модулей fcl-db. Надеюсь стало понятно что я имею в виду.
В случае если предыдущие записи не хранятся, то просмотр записей с отбрасыванием предыдущих результатов сработает. В случае же если предыдущие записи хранятся,,, то не смотря на то что в _моём_ коде они не хранятся _явно_, памяти при большом количестве записей может не хватить, ок да.....
Добавлено спустя 1 минуту 42 секунды:
я имею в виду fcl-db предыдущие записи хранит или нет. Понятно по крайней мере что все записи сразу не загружаются. Они загружаются постепенно. Вопрос в том, освобождаются ли они постепенно
если память не изменяет то данные остаются у вас до момента когда коннект OFF (т.е. они не нужны).
Т.е. то что вытянули осталось в датасете... Память "отжираетса" в зависимости от их количества. О "очистке" данных после получения не слышал (и не встречал). Да и по логике - зачем их очищать (вдруг понадобятся). Вот когда конект оф тогда и удаляются данные.
Хотя, может существуют просвещенные более чем я
Исправите...
угу...
Если загружать порциями то не будет никаких "загрузок" памяти.
К примеру: загрузили 100 записей, обработали, полезли за новыми (предварительно "очистив" датасет от предыдущих).
п.с.
упс: основы баз данных
Т.е. то что вытянули осталось в датасете... Память "отжираетса" в зависимости от их количества. О "очистке" данных после получения не слышал (и не встречал). Да и по логике - зачем их очищать (вдруг понадобятся). Вот когда конект оф тогда и удаляются данные.
Хотя, может существуют просвещенные более чем я
памяти при большом количестве записей может не хватить
угу...
Вот в этом примере результат загружается в переменную a, потом она затирается.
Если загружать порциями то не будет никаких "загрузок" памяти.
К примеру: загрузили 100 записей, обработали, полезли за новыми (предварительно "очистив" датасет от предыдущих).
п.с.
основы SQl вроде как
упс: основы баз данных
sim-sim писал(а):Если загружать порциями то не будет никаких "загрузок" памяти.
К примеру: загрузили 100 записей, обработали, полезли за новыми (предварительно "очистив" датасет от предыдущих).
Что-то я не понимаю, как это реализовать.
Вот я делаю например запрос select * from Table1; потом делаю query.Next в цикле, а как сделать загрузку по 100 записей, например, я что-то не понимаю. Можно в двух словах плз?
двух словах плз
эээх-ух и ах
Кратко. http://freepascal.ru/article/lazarus/20090720000443/ а более подробно - гугл
- EmeraldMan
- постоялец
- Сообщения: 149
- Зарегистрирован: 16.10.2008 08:41:51
- Откуда: Белгород
- Контактная информация:
hinst писал(а):Получается как-то немного тупо. Когда в Query перебираешь полученные записи методом Next, то предыдущие уже просмотренные должны освобождаться, к ним же всё равно нельзя вернуться, метода Back или Previous нету
Как так нету?
SQLQuery.Next; SQLQuery.Prior; а так же SQLQuery.First и SQLQuery.Last. Можно воспользоваться ещё и SQLQuery.MoveBy(Num);
Причем обнаружил интересную особенность: бывает, что когда делаешь большую выборку, то SQLQuery.RecordCount показывает явно меньшее кол-во записей. А если выполнить "SQLQuery.Last; SQLQuery.First;", а затем запросить SQLQuery.RecordCount, то покажет точное число.
Есть-ли возможность получить одной строкой (с разделителями полей) данные текущей записи?
TSQLQuery.GetCurrentRecord(p: pansichar) - может это как-то можно преобразовать в строку?
TSQLQuery.GetCurrentRecord(p: pansichar) - может это как-то можно преобразовать в строку?
VirtUX писал(а):Есть-ли возможность получить одной строкой (с разделителями полей) данные текущей записи?
Код: Выделить всё
s := '';
for i := 0 to Query.FieldDefs.Count -1 do begin
if s= '' then
s := Query.Fields[i].AsString
else
s := s + ';' + Query.Fields[i].AsString;
end;
2 hovadur я не про это спрашивал. А про:
Добавлено спустя 2 минуты 33 секунды:
Перерыл код, и закралось подозрение, что TSQLQuery.GetCurrentRecord(p: pansichar) - не реализовано. Т.к кроме как в предке TDataset (begin Result := false; end;), больше переопределений нет
Код: Выделить всё
for i := 1 to Query.RecordCount do begin
s += Query.(Record целиком с разделителями полей) + Char(Разделитель записей);
end;
Delete(s, length(s), 1)Добавлено спустя 2 минуты 33 секунды:
Перерыл код, и закралось подозрение, что TSQLQuery.GetCurrentRecord(p: pansichar) - не реализовано. Т.к кроме как в предке TDataset (begin Result := false; end;), больше переопределений нет
- debi12345
- долгожитель
- Сообщения: 5761
- Зарегистрирован: 10.05.2006 23:41:15
- Откуда: Ташкент (Узбекистан)
TQuery вызываешь метод Next. Вопрос вот в чём: при этом все данные получаются все сразу, и я потом только их перебираю, или же они получаются некими порциями, по одной штуке,
Это называется вроде как "window" (сопрягается с БД-курсором) - больное место DB-компонентов. Если вытаскивать все записи - в плюсах имеешь точное количество записей, правильную навигацию и скроллинг - но может не хватить памяти и уведешь комп в крайне тормознутый своппинг ( особенно если таких прожорливых компонентов много).
В MSE, после жалоб на кривой дельфевский скроллинг в БД-гридах и списках - даже пришлось реализовывать оба варианта - если приаттаченные компоненты для корректного скроллинга требуют всех записей, то вытаскиваются все. Если не требуются - вытаскивается и обновляется только "window".
Query.RecordCount
Чрезвычайно медленная операция в FCL-DB, потому что записи здесь, из соображения поддержания "window - представлены связанным списком, и узнать их количество можно только дойдя до последнего элемента этого списка.
Чтобы этого избежать, например в MSE список заменили на динамический массив записей фиксированного размера (вместо строк хранятся их указатели).
Добавлено спустя 57 минут 10 секунд:
SQLQuery.GetCurrentRecord(p: pansichar) - может это как-то можно преобразовать в строку?
Там может быть куча бинарных данных -как их преобразуешь ?
как сделать загрузку по 100 записей,
SQL :
Код: Выделить всё
select * from Table1 OFFSET x LIMIT y;или "window"
Код: Выделить всё
query.FetchRows := y;?
hinst писал(а):Получается как-то немного тупо. Когда в Query перебираешь полученные записи методом Next, то предыдущие уже просмотренные должны освобождаться, к ним же всё равно нельзя вернуться, метода Back или Previous нету
unidirectional
Есть - TDataSet - класс (в общем-то, абстракный), предназначен для именованного доступа к набору данных (никаких связанных списков и прочей ереси для "ускорения" - только структура и данные, которые читаются лишь в тот момент, когда нужны).
TQuery - реализация это доступа с использованием TSQLConnection (естественно, с буферизацией)
Очень часто данные по мере загрузки буфиризуются, чтобы "меньше грузить сервер", потому что это олдскульно (так было принято раньше по множеству причин технических причин, сейчас они уже давно неактульаны, но "потому что никому не нужно грузить больше, чем может увидеть", "для этого есть гибкий поиск, пускай правильно ищут" и прочая ерунда гипнотизеров).
Если Вы хотите реализовать более "оптимальную" работу с памятью, то придётся разобраться с тем, как устроены эти компоненты и реализовать свой собственный "умный буфер".
Проблема с "неверным" количеством записей возникает для случаев, когда получение данных ещё не завершено (сервер их тоже не загрузил ещё не знает). Фича очень удобна при работе с большими объемами данных (в частности, обеспечивает возможность по индексам получить большую выборку и потом со смаком её тянуть с сервера не вляпываясь в полное зависание базы и прочие недоразумения) или получать только первые данные, когда все сразу они явно не нужны, а сервак тогда сможет обработать намного больше клиентов. Чтобы этого избежать, нужно сразу фечить все данные.
TQuery - реализация это доступа с использованием TSQLConnection (естественно, с буферизацией)
Очень часто данные по мере загрузки буфиризуются, чтобы "меньше грузить сервер", потому что это олдскульно (так было принято раньше по множеству причин технических причин, сейчас они уже давно неактульаны, но "потому что никому не нужно грузить больше, чем может увидеть", "для этого есть гибкий поиск, пускай правильно ищут" и прочая ерунда гипнотизеров).
Если Вы хотите реализовать более "оптимальную" работу с памятью, то придётся разобраться с тем, как устроены эти компоненты и реализовать свой собственный "умный буфер".
Проблема с "неверным" количеством записей возникает для случаев, когда получение данных ещё не завершено (сервер их тоже не загрузил ещё не знает). Фича очень удобна при работе с большими объемами данных (в частности, обеспечивает возможность по индексам получить большую выборку и потом со смаком её тянуть с сервера не вляпываясь в полное зависание базы и прочие недоразумения) или получать только первые данные, когда все сразу они явно не нужны, а сервак тогда сможет обработать намного больше клиентов. Чтобы этого избежать, нужно сразу фечить все данные.
