Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 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
1-65517
Max_
2003-10-08 13:17
2003.10.20
TreeView и переход на выделенный Node?


3-65326
atruhin
2003-09-28 07:34
2003.10.20
Помогите.Плз. Чем вскрыть пароль BD paradox. Чтоб бесплатно.


3-65357
glow
2003-09-23 10:15
2003.10.20
Снова SQL


14-65622
Step[B.M.]
2003-09-28 23:21
2003.10.20
Ужасно интересная задача о которой вряд-ли кто слышал :)


1-65414
Kiril
2003-10-07 21:34
2003.10.20
Как при нажатии на кнопку запустить другой exe?