Переход с Interbase на Firebird

Запросы, планы, оптимизация запросов, ...

Модераторы: kdv, CyberMax

dimitr
Разработчик Firebird
Сообщения: 888
Зарегистрирован: 26 окт 2004, 16:20

Сообщение dimitr » 30 ноя 2005, 12:23

S.H.S писал(а):Так все таки, что мне где в FB2.0 подкрутить, чтобы количество чтений было примерно одинаковое.
Галки "ускорить селекты" в конфиге нет.
S.H.S писал(а):Запросов я не прячу, просто вопрос не в них.
Нам это до сих пор не ясно. Если тормозит конкретный запрос, значит там наверяка в 2.0 другой план.
S.H.S писал(а):Не хотелось бы показаться полным идиотом, но может кто-нибуди подскажет, где можно почитать про "ФЕТЧ". Или хотя бы в двух словах, что такое полный и частичный фетч, и где это менять (если это возможно).
Фетч - это выборка одной записи из курсора, т.е. вызов isc_dsql_fetch, IBQuery1.Next и т.п.

S.H.S
Сообщения: 65
Зарегистрирован: 25 ноя 2005, 02:18

Сообщение S.H.S » 30 ноя 2005, 14:07

kdv писал(а):давай еще раз уточним:
1. в обоих случаях ты проводишь тест на localhost (НЕ локальный коннект), по tcp, или на удаленном сервере, по tcp. Так?
2. тестируешь в IBExpert, в обоих случаях жмешь
а) кнопку зеленого треугольника при выполнении запроса (выбрать только часть записей, помещающихся в грид)
б) кнопку двойного треугольника (выбрать ВСЕ записи на клиента, сиречь FetchAll).
.
1. И через tcp/ip пробовал и через localhost (на ноутбуке, который не подключен к сети и точно стоит localhost).
2. Жму и там и там, естественно, зеленый треугольник (или F9)

S.H.S
Сообщения: 65
Зарегистрирован: 25 ноя 2005, 02:18

Сообщение S.H.S » 30 ноя 2005, 14:20

dimitr писал(а):
S.H.S писал(а):Запросов я не прячу, просто вопрос не в них.
Нам это до сих пор не ясно. Если тормозит конкретный запрос, значит там наверяка в 2.0 другой план.
Планы одинаковые. Как они будут разные в 1.5.3 и в 2.0 если структура таблиц одинаковая.

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 30 ноя 2005, 15:17

S.H.S писал(а): Не хотелось бы показаться полным идиотом
Я дико иззиняюсь, но пока что тебе это удаётся с феноменальным успехом. С тебя трое людей, досконально владеющих вопросом, спрашивают совершенно конкретную инфу, необходимую для решения твоего вопроса, а ты вместо этого несёшь какую-то пургу про localhost установленный на ноутбуке и одинаковые планы раз структура одинакова. План одного и того же запроса на одной и той же базе под одним и тем же сервером может измениться в любой момент по мере заполнения таблиц.

Ivan_Pisarevsky
Заслуженный разработчик
Сообщения: 644
Зарегистрирован: 15 фев 2005, 11:34

Сообщение Ivan_Pisarevsky » 30 ноя 2005, 16:26

Штирлиц стоял на своем... Это была новая пытка Мюллера.

Автор, тебя двое разработчиков файрберда(Дмитрий и Влад) спрашивают вполне простые конкретные вещи, а вместо простого внятного ответа какие-то сопли-слезы, что нифига не работает. Может тебя утешит твоя ненаглядная? А тут народ обычно таки технические проблемы решает... :lol:

S.H.S
Сообщения: 65
Зарегистрирован: 25 ноя 2005, 02:18

Сообщение S.H.S » 30 ноя 2005, 16:37

Я просто хочу знать, почему на Ib и на FB 1.5.3 одно количество чтений, а на FB 2.0 другое, в запросе SELECT id FROM table, при одной и той же структуре баз, при одинаковом подключении (например через localhost), при стандартных настройках серверов. ВОТ И ВСЕ.

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 30 ноя 2005, 19:15

Нверное потому что строка подключения через локалхост выглядит примерно так:

'c:/bases/mybase.gdb'

?

S.H.S
Сообщения: 65
Зарегистрирован: 25 ноя 2005, 02:18

Сообщение S.H.S » 30 ноя 2005, 19:36

Merlin писал(а):Нверное потому что строка подключения через локалхост выглядит примерно так:
'c:/bases/mybase.gdb'
?
И что? :?:

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 30 ноя 2005, 19:56

а то, что "строка подключения через локалхост" на самом деле должна выглядеть так:
localhost:c:/bases/mybase.gdb

про разницу между локальным коннектом (без имени сервера) и сетевым тебе сразу упомянули.

S.H.S
Сообщения: 65
Зарегистрирован: 25 ноя 2005, 02:18

Сообщение S.H.S » 01 дек 2005, 00:44

Привычка - сильное дело. В IB что локальный сервер что localhost разница не велика. Я не обратил внимание, что на буке (с локальным сервером) и в сети даже структура баз разная (я ведь перенес метадату, а не файл базы). И что на локальном сервере не подключится файл сетевой базы.

У меня будет последний вопрос: Для чего так было сделано?

Всех благодарю за терпение. Особая благодарность Админу за четкий ответ. И принашу извинения Dimitr'ию за то, что его не совсем понял, он то правильно ответил еще в самом начале.

А да еще. Пойду завтра смотреть откуда же эта задержка в 4 сек. Я знаю, что FB 2.0 более строг к написанию запросов. Буду разбираться. :wink:

dimitr
Разработчик Firebird
Сообщения: 888
Зарегистрирован: 26 окт 2004, 16:20

Сообщение dimitr » 01 дек 2005, 13:36

S.H.S писал(а):Для чего так было сделано?
Ты про что именно? А то мы много чего успели обсудить :)

S.H.S
Сообщения: 65
Зарегистрирован: 25 ноя 2005, 02:18

Сообщение S.H.S » 04 дек 2005, 00:48

..."Вернусь опять к баранам."

Вот запрос, который в Ib и в Fb:

SELECT base_id, goods_id, serial_num
FROM base
WHERE goods_id=1199 AND
sell_date IS NULL AND
warranty_date IS NULL AND
base_id NOT IN (SELECT base_id FROM comps WHERE base_id IS NOT NULL)
ORDER BY serial_num

В Ib результат:
Plan
PLAN (COMPS INDEX (RDB$FOREIGN15))
PLAN SORT ((BASE INDEX (RDB$FOREIGN10)))

Adapted Plan
PLAN (COMPS INDEX (INTEG_40)) PLAN SORT ((BASE INDEX (INTEG_35)))

------ Performance info ------
Prepare time = 0ms
Execute time = 40ms
Avg fetch time = 1,74 ms
Current memory = 9,211,869
Max memory = 9,496,859
Memory buffers = 2,048
Reads from disk to cache = 0
Writes from cache to disk = 0
Fetches from cache = 4,612

В Fb результат:
Plan
PLAN (C NATURAL)
PLAN SORT ((BASE INDEX (GOODS_BASE_FK)))

Adapted Plan
PLAN (C NATURAL) PLAN SORT ((BASE INDEX (GOODS_BASE_FK)))

------ Performance info ------
Prepare time = 0ms
Execute time = 1s 963ms
Avg fetch time = 85,35 ms
Current memory = 678,400
Max memory = 702,376
Memory buffers = 2,048
Reads from disk to cache = 0
Writes from cache to disk = 6
Fetches from cache = 1,241,434

Почему такая разница, таблицы же одинаковые. Fb как бы не видит индекс внешнего ключа.

Таблицы:

CREATE TABLE BASE (
BASE_ID INTEGER NOT NULL,
GOODS_ID INTEGER NOT NULL,
BUY_DATE DATE,
SUPPLIER_ID INTEGER NOT NULL,
BUY_PRICE DECIMAL(5,2),
SERIAL_NUM VARCHAR(30),
SELL_DATE DATE,
LOGIN VARCHAR(10),
WARRANTY_DATE DATE
);

ALTER TABLE BASE ADD CONSTRAINT BASE_PK PRIMARY KEY (BASE_ID);

ALTER TABLE BASE ADD CONSTRAINT GOODS_BASE_FK FOREIGN KEY (GOODS_ID) REFERENCES GOODS (GOODS_ID);
ALTER TABLE BASE ADD CONSTRAINT SUPPLIERS_BASE_FK FOREIGN KEY (SUPPLIER_ID) REFERENCES SUPPLIERS (SUPPLIER_ID);


CREATE TABLE COMPS (
COMPS_ID INTEGER NOT NULL,
COMPS_NUM INTEGER NOT NULL,
CATEGORY_ID INTEGER,
GOODS_ID INTEGER,
PRICE NUMERIC(5,2),
PRICE_RB INTEGER,
BASE_ID INTEGER,
METKA INTEGER
);

ALTER TABLE COMPS ADD CONSTRAINT COMPS_PK PRIMARY KEY (COMPS_ID);

ALTER TABLE COMPS ADD CONSTRAINT BASE_COMPS_FK FOREIGN KEY (BASE_ID) REFERENCES BASE (BASE_ID);
ALTER TABLE COMPS ADD CONSTRAINT CATEGORY_COMPS_FK FOREIGN KEY (CATEGORY_ID) REFERENCES CATEGORY (CATEGORY_ID);
ALTER TABLE COMPS ADD CONSTRAINT GOODS_COMPS_FK FOREIGN KEY (GOODS_ID) REFERENCES GOODS (GOODS_ID);

CREATE INDEX COMPS_IDX1 ON COMPS (COMPS_NUM);

Я понимаю, что запись base_id NOT IN (SELECT base_id FROM comps WHERE base_id IS NOT NULL) это не красиво, но все же бывает необходимость и в этом.
Проверил разницу выполнения больше половины запросов, используемых в моей программе, в Ib и Fb, в Fb выполнение во многих запросах быстрее: где на 10 мс, а где и на 400 мс. Но этот запром меня просто убил. Подскажите, как ускорить этот запрос FB. Плиз-з.

hvlad
Разработчик Firebird
Сообщения: 1244
Зарегистрирован: 21 мар 2005, 10:48

Сообщение hvlad » 04 дек 2005, 11:55

S.H.S писал(а):..."Вернусь опять к баранам."
С этих "баранов" нужно было начинать.
Статистику индексов обновлял ?
Алиасы к таблицам и к полям прикрути, как минимум к base_id

dimitr
Разработчик Firebird
Сообщения: 888
Зарегистрирован: 26 окт 2004, 16:20

Сообщение dimitr » 04 дек 2005, 12:20

S.H.S писал(а):base_id NOT IN (SELECT base_id FROM comps WHERE base_id IS NOT NULL)
Двойка не использует индекс для NOT IN. Потому что иначе (в том же IB) возвращаются неправильные данные. Пример можно увидеть тут: http://sourceforge.net/tracker/index.ph ... tid=109028

Я предпочитаю корректный, но медленный результат быстрому.

Попробуй переписать запрос на левый джойн с IS NULL во внешнем предикате, что-то типа:

Код: Выделить всё

SELECT b.base_id, b.goods_id, b.serial_num
FROM base b
LEFT JOIN comps c on b.base_id = c.base_id
WHERE b.goods_id=1199
AND b.sell_date IS NULL
AND b.warranty_date IS NULL
AND c.base_id IS NULL
ORDER BY serial_num

S.H.S
Сообщения: 65
Зарегистрирован: 25 ноя 2005, 02:18

Сообщение S.H.S » 04 дек 2005, 20:20

dimitr писал(а): Попробуй переписать запрос на левый джойн с IS NULL во внешнем предикате, что-то типа:

Код: Выделить всё

SELECT b.base_id, b.goods_id, b.serial_num
FROM base b
LEFT JOIN comps c on b.base_id = c.base_id
WHERE b.goods_id=1199
AND b.sell_date IS NULL
AND b.warranty_date IS NULL
AND c.base_id IS NULL
ORDER BY serial_num
Это конечно хорошо, даже очень хорошо, но когда вместо 1199 появляется NULL plan координально меняется:
С такого :lol::
Plan
PLAN SORT (JOIN (B INDEX (GOODS_BASE_FK), C INDEX (BASE_COMPS_FK)))

На такой :cry::
Plan
PLAN SORT (JOIN (B NATURAL, C INDEX (BASE_COMPS_FK)))

Скорость, соответственно, падает на 2 секунды.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 04 дек 2005, 21:25

замени null на 0. И сразу станет легче.

S.H.S
Сообщения: 65
Зарегистрирован: 25 ноя 2005, 02:18

Сообщение S.H.S » 04 дек 2005, 23:00

kdv писал(а):замени null на 0. И сразу станет легче.
С радастью, но это зависимый запрос. Мало того, этот NULL много раз в программе используется (боюсь ошибиться).

S.H.S
Сообщения: 65
Зарегистрирован: 25 ноя 2005, 02:18

Сообщение S.H.S » 04 дек 2005, 23:18

:P Нашел !!!

Простое и, может быть, туповатое решение - NULL*1.
Немного не понимаю почему работает, но работает. Сейчас пойду проверять как он себя будет вести.

Всем спасибо !!!

Ivan_Pisarevsky
Заслуженный разработчик
Сообщения: 644
Зарегистрирован: 15 фев 2005, 11:34

Сообщение Ivan_Pisarevsky » 06 дек 2005, 08:27

С нулл-ами я б вообще обошелся по законам военного времени. Без суда и следствия...

base_id NOT IN (SELECT base_id FROM comps WHERE base_id IS NOT NULL)

ALTER TABLE COMPS ADD CONSTRAINT BASE_COMPS_FK FOREIGN KEY (BASE_ID) REFERENCES BASE (BASE_ID);

Что мешает в таблице base добавить строку-заглушку для всех несознательных записей которые not in?

Вы торгуете мелкой бижутерией?
BUY_PRICE DECIMAL(5,2),
PRICE NUMERIC(5,2), :roll:

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 06 дек 2005, 12:58

туповатое решение - NULL*1
оно такое потому, что NULL * 1 = NULL.

Ответить