Текущий архив: 2003.10.20;
Скачать: CL | DM;
Вниз
Тормозит FireBird Найти похожие ветки
← →
Denkop © (2003-09-30 14:01) [0]Юзаю firebird WI-V1.0.3.972, версия 3-х недельной давности.
Делаю примерно такой запрос:
SELECT * FROM MAINTABLE T1
LEFT JOIN ORG_GROUP T2 ON T1.ID_GROUP=T2.ID
LEFT JOIN REG_GROUP T3 ON T1.ID_REG=T3.ID
LEFT JOIN TOWN_GROUP T4 ON T1.ID_TOWN=T4.ID
Поля X.NAME, X.ID все проиндексированы (ID-первич,NAME-вторич);
Для доступа использую стандартные компоненты с вкладки InterBase (IBDataBase,IBTransaction,IBQuery).
Структура MAINTABLE (примерно 100000 записей):
CREATE TABLE MAINTABLE (
ID INTEGER NOT NULL,
ID_GROUP INTEGER,
NAME VARCHAR(150),
TEL VARCHAR(20),
FAX VARCHAR(20),
FIO VARCHAR(150),
EMAIL VARCHAR(240),
WEB VARCHAR(240),
ADDRESS VARCHAR(240),
ID_REG INTEGER,
ID_TOWN INTEGER,
ZIP VARCHAR(10)
);
остальные таблицы классификаторы (ID, NAME)
На машине Authlon 1400/256mb/40HDD Seagate 7200 Ata100 этот запрос выполняется около минуты!
В настройках FIB:
Database Cash: 2048
Map size: 50698
Как можно повысить быстродействие выборки?
← →
Nikolay M. © (2003-09-30 14:08) [1]Нужны обязательно JOIN-ы? Через WHERE не прокатит?
А если сделать лукапные поля на клиенте? А я так вообще иногда делаю так: загоняю маленькие справочники, отсортированные по ключу, в память и приделываю Calculated-поле, в котором делается поиск по ключу в этом массиве в памяти методом деления отрезка пополам. Получается более чем резво. Если памяти, конечно, много...
← →
Vlad © (2003-09-30 14:08) [2]А причем тут индексы, когда у тебя FullScan по таблице ?
Индексы тебе тут сильно не помогут. Время для 100000 записей нормальное.
← →
Alexandr © (2003-09-30 14:20) [3]план. нужен план.
← →
Johnmen © (2003-09-30 14:22) [4]1. Может у тебя справочники очень большие.
2. LEFT JOIN очень долгая операция
3. М.б. надо все-таки JOIN ? Он очень быстр к тому же...
← →
Mike Kouzmine © (2003-09-30 14:25) [5]Alexandr © (30.09.03 14:20) [3] Ваша правда.
← →
Denkop © (2003-09-30 14:25) [6]Nikolay M.>>
Вся беда в том, что все вместе взятые справочники содержат не более 1000 записей, а держать в памяти 100000 записей на 256Mb наврядли получится. Даже если это получится, то всё это дело со временем сгрузится в подкачку, т.к. на машине стоит куча софта, которым юзверь не прочь попользоваться.
пробовал и через лукапы связывать, толку нет... таже картина
Vlad >>
А какой выход с положения, может есть смысл перейти на другую СУБД? Ведь это справочник и лично меня бы очень сильно разозлил факт выборки длительностью в минуту!!
← →
Карелин Артем © (2003-09-30 14:25) [7]Лично я пользуюсь вложенными циклами For select в хранимых процедурах. Летает со свистом при нормальных индексах. Фетчинг идет сразу или фетчится по мере надобности? Если первое, то почти нормально. Если второе - дело пахнет керосином.
← →
Vlad © (2003-09-30 14:27) [8]Denkop © (30.09.03 14:25) [6]
Выход из положения м.б. следующий. Отказаться от Query и пользоваться IBDataSet. Там, если мне не изменяет память можно устанавливать BufferChunks, т.е. будут подргужаться не все сразу записи.
← →
Denkop © (2003-09-30 14:33) [9]Карелин Артем > поясни пож
Alexandr> ....
← →
Карелин Артем © (2003-09-30 14:34) [10]А разве в TIbQuery сразу идет загрузка всех записей? Там читается по мере необходимости, если конечно FetchAll не вызывать. Если мне не изменяет память :)
← →
Vlad © (2003-09-30 14:39) [11]>Карелин Артем © (30.09.03 14:34) [10]
Возможно, только вот я что-то не нашел как в IBQuery этим делом управлять можно. Хотя бы курсор установить сервер/клиент. Такое впечатление что он фетчит записи так как сам захочет. И неясно чем определяется эта "мера необходимости"
← →
Alexandr © (2003-09-30 14:41) [12]мера необходимости определяется программистом, который управляет размером грида, в первую очередь.
А уж грид возмет сколько ему надо, а IBQuery отдаст сколько попросят.
← →
Карелин Артем © (2003-09-30 14:43) [13]Vlad © (30.09.03 14:39)
Ну это... При вызове Next/Last и фетчатся записи. А напрямую по-моему облом.
← →
Nikolay M. © (2003-09-30 14:44) [14]
> Denkop © (30.09.03 14:25) [6]
> Вся беда в том, что все вместе взятые справочники содержат
> не более 1000 записей,
В вышеприведенном примере в запросе используются 3 справочника, в каждом 2 поля: ID, Name. Допустим, ка каждую запись примерно приходится по 200 байт => справочник занимает 200КБ, 3 справочника: 600КБ, пусть будет мегабайт: имхо, с 256 МБ можно позволить себе такую роскошь...
Да, еще в догонку: а тебе действительно нужно получать все 100 000 записей на клиенте? В SQL FB есть что-то вроде TOP, LIMIT или подобного для ограничения возвращаемого кол-ва строк?
← →
Alexandr © (2003-09-30 14:44) [15]обсуждение плавно переходит в маразм...
сорри, не удержался.
← →
Vlad © (2003-09-30 14:46) [16]>Alexandr © (30.09.03 14:41) [12]
По вашему, размер грида у автора вмещает 100 тыс. видимых записей ?
Судя по времени выполнения запроса, приведенному автором, происходит именно FetchAll, а уж почему так происходит - автору виднее.
← →
Карелин Артем © (2003-09-30 15:01) [17]Denkop © (30.09.03 14:33) [9]
Завтра после обеда стукни ко мне в аську, я как раз возьму свою базу. По руками примера нет, сочинять неохота.
Хотя дело видимо в другом. Я тоже склоняюсь к FetchAll. Ну или в перемещении в конец набора данных.
← →
Denkop © (2003-09-30 15:14) [18]Nikolay M. >> как я понял все тормоза именно с выборкой where, а чтобы это дело ускорить в памяти нужно держать и MAINTABLE.
Про fetchall: я собственноручно прописал
procedure TDataModule1.MainTableAfterOpen(DataSet: TDataSet);
begin
DataModule1.MainTable.FetchAll;
end;
Эту глупость я убрал, но
даже без этого куска в грид загружаются все выбранные записи
Vlad > Получается так...
Выбираю так:
SELECT * FROM MAINTABLE T1
LEFT JOIN ORG_GROUP T2 ON T1.ID_GROUP=T2.ID
LEFT JOIN REG_GROUP T3 ON T1.ID_REG=T3.ID
LEFT JOIN TOWN_GROUP T4 ON T1.ID_TOWN=T4.ID
WHERE T1.ID_REG=121
ORDER BY T3.NAME, T4.NAME, T2.NAME, T1.NAME
Раза полтора быстрее, а в грид загружаются все выбранные 40000 записей...
З.Ы.
сори, в посте Denkop © (30.09.03 14:01) неточность
запрос выглядит так:
SELECT * FROM MAINTABLE T1
LEFT JOIN ORG_GROUP T2 ON T1.ID_GROUP=T2.ID
LEFT JOIN REG_GROUP T3 ON T1.ID_REG=T3.ID
LEFT JOIN TOWN_GROUP T4 ON T1.ID_TOWN=T4.ID
WHERE ((UPPER(T1.NAME COLLATE PXW_CYRL) LIKE "%чёто%")
AND (T1.ID_REG=121)
ORDER BY T3.NAME, T4.NAME, T2.NAME, T1.NAME
← →
Deniz © (2003-09-30 15:20) [19]>Denkop ©
Специально создал тест 100 000 записей твоей структуры наполнил в IBExpert -> Test data generation
select * from TestTable
IBQuery1.Open;
~ 0.4 s
---
IBDatabase1.Open;
IBQuery1.Open;
~0.9 s
---
IBQuery1.FetchAll;
~32 s
---
Машина P-II 400 RAM 384, FB 1.0.2.908, IBX 7.08
← →
Vlad © (2003-09-30 15:27) [20]>((UPPER(T1.NAME COLLATE PXW_CYRL) LIKE "%чёто%")
Вот тут происходит тормоз.
like( %чёто%) будет замедлять выборку
← →
Vlad © (2003-09-30 15:37) [21]>Denkop © (30.09.03 15:14) [18]
Кстати, если не делать FetchAll,в грид загружаются не все выбранные записи, а только видимые. А затем, по мере скроллинга подгужаются с сервера.
← →
Denkop © (2003-09-30 15:48) [22]Усё, я понатыкал fetchall везде где можно.
Нехорошая привычка возникла после того как я пытался почитать незафетченные данные, я тогда чуть голову не свернул себе и всем окружающим.
Всем спасибо, вопрос снят, опять глупость...
Страницы: 1 вся ветка
Текущий архив: 2003.10.20;
Скачать: CL | DM;
Память: 0.52 MB
Время: 0.022 c