powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Опять про деревья и время выполнения ...
25 сообщений из 43, страница 1 из 2
Опять про деревья и время выполнения ...
    #32645085
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сообственно вопрос следующий:

Есть три таблицы
GOODS - товары 10000 записей
ID
PARENT
NAME

CUST - клиенты 2000 записей
ID
PARENT
NAME

DOC - отгрузки (YY-год, ММ-месяц и индекс GOODS,CUST,YY,MM) - 100 000 записей
GOODS
CUST
YY
MM
QTY
PRICE


Нужно выдать результаты в виде таблицы():
Группа Товаров, Кол-во Январь, Кол-во Февраль, ..., Кол-во Декабрь, Кол-во Итого;

Создал две рекурсивные процедуры, которые отбирают нужных клиентов и товары и сделал ХП

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
  FOR SELECT
  G.NAME,
  SUM(CASE WHEN D.MM =  1  THEN QTY ELSE  0  END),
  .....
  SUM(CASE WHEN D.MM =  12  THEN QTY ELSE  0  END)
  FROM DOC D
  JOIN GETGOODS(:GID) G ON (G.ID = D.GOODS)
  JOIN GETCUST(:CID) C ON (C.ID = D.CUST)

Все работает точно до копейки, но быстродействие ~ 20 минут , если выбирать корневую группу товаров и клиентов.

Может есть какие-то другие решения ?

Best regards,
Dnico.
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32645210
Лентяй
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А попробуй от клентов, скажем, плясять :
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
  FOR SELECT
  G.NAME,
  SUM(CASE WHEN D.MM =  1  THEN QTY ELSE  0  END),
  .....
  SUM(CASE WHEN D.MM =  12  THEN QTY ELSE  0  END)
  FROM GETCUST(:CID) C 
  JOIN DOC D ON (C.ID = D.CUST)
  JOIN GETGOODS(:GID) G ON (G.ID = D.GOODS)
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32645252
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну вообщем-то выигрышь составил 12%.
Это уже радует ...

Best regards,
Dnico.
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32645354
Лентяй
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну что еще посоветовать можно не видя текстов процедур и планов...
Если там все нормально, то может стоит завести еще одну табличку с агрегатами по клиенту, товару (группе товаров?) за месяц.
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32645687
olol
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dnico
...быстродействие ~ 20 минут ...

А если так попробывать:

[/quot]
CREATE PROCEDURE peDocGidCid (GID INTEGER, CID INTEGER)
RETURNS (NAME CHAR(40),
QTY1 DOUBLE PRECISION, QTY2 DOUBLE PRECISION,
QTY3 DOUBLE PRECISION, QTY4 DOUBLE PRECISION,
QTY5 DOUBLE PRECISION, QTY6 DOUBLE PRECISION,
QTY7 DOUBLE PRECISION, QTY8 DOUBLE PRECISION,
QTY9 DOUBLE PRECISION, QTY10 DOUBLE PRECISION,
QTY11 DOUBLE PRECISION, QTY12 DOUBLE PRECISION
QTY DOUBLE PRECISION)
AS DECLARE VARIABLE MM INTEGER;
BEGIN
SELECT NAME FROM GOODS WHERE GID = :GID INTO :NAME;
QTY = 0; QTY1 = 0; QTY2 = 0; QTY3 = 0; QTY4 = 0; QTY5 = 0; QTY6 = 0;
QTY7 = 0; QTY8 = 0; QTY9 = 0; QTY10 = 0; QTY11 = 0; QTY12 = 0;
FOR SELECT MM,QTY FROM DOC WHERE GID = :GID AND CID = :CID
INTO :MM,:QTY
DO BEGIN
IF (MM = 1) THEN QTY1 = QTY1 + QTY;
ELSE IF (MM = 2) THEN QTY2 = QTY2 + QTY;
ELSE IF (MM = 3) THEN QTY3 = QTY3 + QTY;
ELSE IF (MM = 4) THEN QTY4 = QTY4 + QTY;
ELSE IF (MM = 5) THEN QTY5 = QTY5 + QTY;
ELSE IF (MM = 6) THEN QTY6 = QTY6 + QTY;
ELSE IF (MM = 7) THEN QTY7 = QTY7 + QTY;
ELSE IF (MM = 8) THEN QTY8 = QTY8 + QTY;
ELSE IF (MM = 9) THEN QTY9 = QTY9 + QTY;
ELSE IF (MM = 10) THEN QTY10 = QTY10 + QTY;
ELSE IF (MM = 11) THEN QTY11 = QTY11 + QTY;
ELSE IF (MM = 12) THEN QTY12 = QTY12 + QTY;
END
QTY = QTY1 + QTY2 + QTY3 + QTY4 + QTY5 + QTY6
+ QTY7 + QTY8 + QTY9 + QTY10 + QTY11 + QTY12;
END
[/quot]

SELECT NAME... - лучше бы перенести во внешнюю ХП (которая выбирает GID) чтоб неделать ее на каждый CID...
и QTY =... - туда же...

ELSE IF... заменить на CASE...
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32645968
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
olol
Спасибо, мне эта идея тоже приходила в голову и я ее использовал в старых версиях FB, когда небыло CASE. Сейчас про такой подход забыл ...

Попробую ....

Best regards,
Dnico.
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32646093
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Увы ... Одно и тоже.

Best regards,
Dnico.
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32646518
olol
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
автор

Базу на всякий случай бакап/ресторни...

...две рекурсивные процедуры, которые отбирают нужных клиентов и товары...


Можно хоть на них взглянуть... вдруг собака там зарыта...
Почему рекурсивные? и почему две?
Записей в принципе не так уж много, но любое лишнее телодвижение в тысячах на тысячу могут дать большие объемы работы...

Трудно судить о задаче... но если нужен отчет за год по клиентам, то я бы сделал приблизительно так:

[quot]
CREATE PROCEDURE psDocYY (YY INTEGER)
RETURNS (СNAME CHAR(40), GNAME CHAR(40),
QTY1 DOUBLE PRECISION, QTY2 DOUBLE PRECISION,
QTY3 DOUBLE PRECISION, QTY4 DOUBLE PRECISION,
QTY5 DOUBLE PRECISION, QTY6 DOUBLE PRECISION,
QTY7 DOUBLE PRECISION, QTY8 DOUBLE PRECISION,
QTY9 DOUBLE PRECISION, QTY10 DOUBLE PRECISION,
QTY11 DOUBLE PRECISION, QTY12 DOUBLE PRECISION)
AS DECLARE VARIABLE GID INTEGER; DECLARE VARIABLE CID INTEGER;
DECLARE VARIABLE GOODS INTEGER; DECLARE VARIABLE CUST INTEGER;
BEGIN
GOODS = 0; CUST = 0;
FOR SELECT DISTINCT GOODS,CUST FROM GOODS WHERE YY = :YY
INTO :GID,:CID
DO BEGIN
IF (GID <> :GOODS) THEN BEGIN GOODS = GID;
SELECT NAME FROM GOODS WHERE GID = :GID INTO :GNAME; END
IF (CID <> :CUST) THEN BEGIN CUST = CID;
SELECT NAME FROM CUST WHERE CID = :CID INTO :CNAME; END
EXECUTE PROCEDURE peDocGidCid (:GID, :CID)
RETURNING_VALUES :QTY1,:QTY2,:QTY3,:QTY4,:QTY5,:QTY6,
:QTY7,:QTY8,:QTY9,:QTY10,:QTY11,:QTY12;
END
END
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32646564
olol
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
автор

Поторопился и SUSPEND; забыл поставить...
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32647277
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот рекурсия, вибирает все товары принадлежащие группе (IDD)CREATE PROCEDURE GETGOODS (
IDD VARCHAR(10))
RETURNS (
ID VARCHAR(10),
PID VARCHAR(10),
NAME VARCHAR(100),
ISF SMALLINT)
AS
BEGIN
FOR SELECT ID, PARENT, NAME,ISF FROM GOODS WHERE PARENTID = :IDD INTO :ID, :PID, :NAME, :ISF
DO BEGIN
IF (:ISF = 1) THEN
FOR SELECT ID, PID, NAME, ISF FROM GETGOODS (:ID) INTO :ID, :PID, :NAME, :ISF
DO SUSPEND;
ELSE SUSPEND;
END
END

Аналогично и по клиенту. И сам запрос (С планами все ок на 100%):

авторSELECT
SUM(CASE WHEN D.MM = 1 THEN QTY ELSE 0 END),
.....
SUM(CASE WHEN D.MM = 12 THEN QTY ELSE 0 END)
FROM GETCUST(:CID) C
JOIN DOC D ON (C.ID = D.CUST)
JOIN GETGOODS(:GID) G ON (G.ID = D.GOODS)


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
PLAN JOIN (CUST INDEX (CUST_IDX1),CUST INDEX (RDB$PRIMARY8),CUST INDEX (RDB$PRIMARY8))
(GOODS INDEX (GOODS_IDX1))(GOODS INDEX (FK_GOODS))(GOODS INDEX (FK_GOODS))(D INDEX (DOC_IDX2))


Query Time
------------------------------------------------
Prepare       : 16,00 ms
Execute       : 18 015,00 ms
Avg fetch time: 18 015,00 ms

Memory
------------------------------------------------
Current: 10 971 820
Max    : 213 033 996
Buffers: 2 048

Operations
------------------------------------------------
Read   : 10 066
Writes : 0
Fetches: 3 044 864


Enchanced Info:
+--------------------------+-----------+-----------+---------+---------+---------+
|        Table Name        |   Index   | Non-Index | Updates | Deletes | Inserts |
|                          |   reads   |   reads   |         |         |         |
+--------------------------+-----------+-----------+---------+---------+---------+
|                      CUST|        77 |         0 |       0 |       0 |       0 |
|                     GOODS|    510048 |         0 |       0 |       0 |       0 |
|                       DOC|     12797 |         0 |       0 |       0 |       0 |
+--------------------------+-----------+-----------+---------+---------+---------+

Best regards,
Dnico.
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32647372
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мимопроходящий - может хоть ссылочку какую тиснешь? А то совсем закопался. Никаких идей ...

Best regards,
Dnico.
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32647387
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dnico Мимопроходящий - может хоть ссылочку какую тиснешь? А то совсем закопался. Никаких идей ... На какую тему?
Я ж в этом обсуждении не участвую.
На http://ibase.ru про деревья всё прочитал?
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32647409
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да все вроде-бы читал ... только не помогает


Best regards,
Dnico.
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32647421
Мимопроходящий
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DnicoДа все вроде-бы читал ... только не помогает Ну, тогда попробуй подумать.
Иногда помогает.
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32647551
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ладно, тему можно закрывать ... добился 2 минут .
Думаю это предел.

Best regards,
Dnico.
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32647586
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У тебя много чтений GOODS - пляши от них
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32647588
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У тебя много чтений GOODS - пляши от них
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32647880
olol
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Может я чего то не понимаю, но помоему для корневых групп товаров и клиентов GETGOODS и GETCUST выдадут все записи, что составит 10000 * 2000 = ...дофига получается комбинаций и для каждой будет считаться SUM... (при ее наличии в DOC)...

Если там всего 100 000 записей, то их не будет для каждой и по одной за год...

Не лучше ли плясать от DOC получив сначала ...DISTINCT GOODS,CUST FROM DOC WHERE YY = :YY (тогда лишних комбинаций не будет),
а уж потом проверять на их принадлежность GETGOODS и GETCUST и считать SUM...

P.S. что-то я не заметил проверки на YY !!! (помесячно за все года что ли...)
и я бы ID записей не делал VARCHAR(10) !!!
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32647992
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ololМожет я чего то не понимаю, но помоему для корневых групп товаров и клиентов GETGOODS и GETCUST выдадут все записи, что составит 10000 * 2000 = ...дофига получается комбинаций и для каждой будет считаться SUM... (при ее наличии в DOC)...

Если там всего 100 000 записей, то их не будет для каждой и по одной за год...

Не лучше ли плясать от DOC получив сначала ...DISTINCT GOODS,CUST FROM DOC WHERE YY = :YY (тогда лишних комбинаций не будет),
а уж потом проверять на их принадлежность GETGOODS и GETCUST и считать SUM...

Да, это вот интересное решение. Попробую.


ololP.S. что-то я не заметил проверки на YY !!! (помесячно за все года что ли...)

Проверка такая есть конечно, просто сейчас в таблице лежит один год.

olol
и я бы ID записей не делал VARCHAR(10) !!!

К сожалению это отголоски 1С.

Best regards,
Dnico.
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32648027
Лентяй
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
  FOR SELECT
  G.NAME,
  SUM(CASE WHEN D.MM =  1  THEN QTY ELSE  0  END),
  .....
  SUM(CASE WHEN D.MM =  12  THEN QTY ELSE  0  END)
  FROM GETCUST(:CID) C 
  JOIN DOC D ON (C.ID = D.CUST)
  JOIN GETGOODS(:GID) G ON (G.ID = D.GOODS)
hvladУ тебя много чтений GOODS - пляши от них
А не подскажешь, почему так получается? Я так понимаю, что GetGoods выполняется для каждой строки, получившейся при объединении DOC и GETCUST? Абстрактно говоря, оптимизатор рассматривает GetGoods как коррелированный подзапрос? По идее можно сначала вычитать из нее все один раз и результаты объединять. Или все не так? А если так, то в FB 2 есть какие-нибудь планы по этому поводу? Может какие-то хинты ввести, чтобы можно было помочь оптимизатору в таких случаях.

И если то что я написал более-менее похоже на правду - то для того чтобы уменьшить время выполнения запроса, можно результаты выборки из GetGoods вставлять во временную табличку и затем с ней и join-ить.
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32648106
hvlad
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЛентяйА не подскажешь, почему так получается? Я так понимаю, что GetGoods выполняется для каждой строки, получившейся при объединении DOC и GETCUST? Абстрактно говоря, оптимизатор рассматривает GetGoods как коррелированный подзапрос? По идее можно сначала вычитать из нее все один раз и результаты объединять. Или все не так? Насколько я понимаю - да GetGoods вызывается многократно. Но не потому что оптимизатор считает его кореллированным, а потому, что сейчас нет способа скешировать результаты выборки из процедуры и использовать их несколько раз.

ЛентяйА если так, то в FB 2 есть какие-нибудь планы по этому поводу? Есть ;)

ЛентяйИ если то что я написал более-менее похоже на правду - то для того чтобы уменьшить время выполнения запроса, можно результаты выборки из GetGoods вставлять во временную табличку и затем с ней и join-ить.Или пользоваться другой структурой дерева, позволяющей получить необходимую выборку одним запросом без рекурсии.

А временную таблицу если и использовать, то для результатов GETCUST - их должно быть много меньше
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32648371
Лентяй
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hvladНасколько я понимаю - да GetGoods вызывается многократно. Но не потому что оптимизатор считает его кореллированным, а потому, что сейчас нет способа скешировать результаты выборки из процедуры и использовать их несколько раз.Спасибо за разъяснения.
ЛентяйА если так, то в FB 2 есть какие-нибудь планы по этому поводу? hvladЕсть ;)?Улыбка-то, надеюсь, не ехидная?
hvladИли пользоваться другой структурой дерева, позволяющей получить необходимую выборку одним запросом без рекурсии. А можно еще две процедуры в одну объединить и к ней join-ить
hvladА временную таблицу если и использовать, то для результатов GETCUST - их должно быть много меньшеУгу, так лучше будет.
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32648420
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Рекурсивные процедуры - 17 сек
Временные таблицы CUST & GOODS - 8 сек

Best regards,
Dnico.
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32648462
Лентяй
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, по сравнению с 20 минутами очень даже неплохо...
...
Рейтинг: 0 / 0
Опять про деревья и время выполнения ...
    #32648475
Фотография Dnico
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да нет ... там больше записей ... там получилось 2 мин - тоже ничего ...

Best regards,
Dnico.
...
Рейтинг: 0 / 0
25 сообщений из 43, страница 1 из 2
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Опять про деревья и время выполнения ...
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]