Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.05.02;
Скачать: CL | DM;

Вниз

Нужно ускорить выполнение запроса.   Найти похожие ветки 

 
dimm22   (2004-04-05 12:10) [0]

У меня 4 таблицы, и надо мне получить данные из таблиц 1 и 2 путём группирования (group by) таблицы 1 и присоединением(join) к результату полей из таблицы 2. С таблицами 3 и 4 точно такая же ситуация(группирование (group by) таблицы 3 и присоединением(join) к результату полей из таблицы 4). А результат полученный из таблиц 1+2 надо объединить с результатом из таблиц 3+4. Группирование таблицы 1 и присоединение полей из таблицы 2, в моём конкретном случае, проходит порядка 4 секунд. Та же операция с таблицами 3 и 4 порядка 7 секунд. Но если в одном запросе попробовать сделать 1+2 join 3+4,  то получается очень долго (ждал час – не дождался, вырубил.)  Индексы по группируемым и объединяемым полям присутствуют. Сейчас вышел из положения созданием псевдо временной таблицы, в которую пишу результаты запроса к 1+2 таблице, а потом уж объединяю её  с  результатом полученным из 3+4 таблицы. Всё бы ничего, но вставка и удаление в псевдо временную таблицу 5 000- 18 000 записей, не кажется мне хорошим решением. Может можно как-нибудь заставить оптимизатор сначала выполнить запрос 1+2, потом 3+4, а потом уж объединить результаты?


 
Fay ©   (2004-04-05 12:13) [1]

Это, конечно, это не решение, но по опыту знаю - очень хорошо помогает переход на Oracle или MSSQL. 8)


 
Курдль ©   (2004-04-05 12:15) [2]

А не весь запрос глянуть можно?


 
dimm22   (2004-04-05 12:19) [3]


> Fay ©

А там, что? Временными таблицами пользуешься?


 
dimm22   (2004-04-05 12:27) [4]

Ну на самом деле сейчас это оформлено в 2 процедуры.
1)CREATE PROCEDURE INVENT_SKLADA (
   PRMDATA_P DATE)
RETURNS (
   QUANTITY DECIMAL(11,2),
   ID_GOODS INTEGER,
   ART VARCHAR(25),
   NAME_R VARCHAR(45),
   PRICE_SALE DOUBLE PRECISION,
   ID_GOODS2 INTEGER)
AS
begin
for SELECT sum(deposit.quantity), deposit.id_goods, goods.art, goods.name_r, goods.price_sale, goods.id_goods
   FROM goods inner join deposit  on  deposit.id_goods= goods.id_goods where deposit.data_p<=:prmdata_p
   group by deposit.id_goods, goods.art,goods.name_r,goods.price_sale,goods.id_goods
   into    :QUANTITY,:ID_GOODS,:ART,:NAME_R,:PRICE_SALE,:ID_GOODS2
   do
       begin
       suspend;
       end
end
2)CREATE PROCEDURE SKLAD_SITUATION (
   PRM_DATA DATE)
RETURNS (
   QUANTITY DECIMAL(11,2),
   ART VARCHAR(25),
   NAME_R VARCHAR(45),
   PRICE_SALE DOUBLE PRECISION,
   ID_GOODS2 INTEGER)
AS
begin
   execute procedure rashod_sklad_procedure(:prm_data);
   for
    select invent_sklada.id_goods2, invent_sklada.art,  invent_sklada.name_r, invent_sklada.price_sale, invent_sklada.quantity+rashod_sklad_tmp.quantity  from invent_sklada("01.03.2004")
    left join rashod_sklad_tmp  on invent_sklada.id_goods2=rashod_sklad_tmp.id_goods
    into  :id_goods2, :art,  :name_r, :price_sale, :quantity
    do
      begin
       suspend;
  end
end
А потом уж их объединение по полю id_goods, но был и один запрос - результат тот же.


 
Fay ©   (2004-04-05 12:27) [5]

2dimm22
Да хоть как. Всё равно будет намного быстрее.


 
Курдль ©   (2004-04-05 12:34) [6]

Трудно "навскидочку" понять, чего Вы добивались, но не попробовать ли подменить группировку конструкцией

select
 field1,
 field2,
...
 (select SUM(field3) from table2 ...)  as field3
...
from table1


 
dimm22   (2004-04-05 12:41) [7]


> Fay ©   (05.04.04 12:27) [5]

Ну не думаю я, что без использования временных таблиц Oracle или MSSQL сделает это намного быстрее. Там проблема в том, что вторая часть запроса (таблицы 3+4) выполняется каждый раз с новым значением поля, по которому идёт его объединение с результатами из таблиц 1+2. А хотелось бы добится выполнения 1+2, потом 3+4, а потом уж выполнение объединения с этих результатов.


> Курдль ©   (05.04.04 12:34) [6]

А это мысль. Спасибо.


 
Fay ©   (2004-04-05 12:44) [8]

2dimm22   (05.04.04 12:41) [7]
Быстрее и намного. Любым (корректным) способом. С индексами ли, бе них ли... Потому, что IB - тормоз.


 
dimm22   (2004-04-05 12:46) [9]

Кстати, где то месяц назад велась полемика насчёт полезности временных таблиц. Ну так вот на моём опыте могу сказать, что они полезны, во всяком случае, для оптимизации запросов.


 
Shaman ©   (2004-04-05 14:17) [10]

Сначала выполняй join, а потом группируй


 
dimm22   (2004-04-05 14:33) [11]


> Shaman ©   (05.04.04 14:17) [10]

Понятное дело это приведёт к ускорению запроса, но дело в том, что не могу я так сделать. Пока я не сгруппировал у меня просто нет данных для join.

Кстати слышал краем уха, что в Ibase 7.1 есть временные таблицы. Так ли это?


 
serge35   (2004-04-05 14:33) [12]

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


 
serge35   (2004-04-05 14:34) [13]

А делать временные таблицы может и неправильно,
а вот постоянную я бы сделал и возможно, что не одну.


 
dimm22   (2004-04-05 14:49) [14]


> А делать временные таблицы может и неправильно,
> а вот постоянную я бы сделал и возможно, что не одну.

Ничего не понял. Я ж говорю, использовал псевдо временные таблицы, те они на самом деле постоянные, а вот использование настоящих временных таблиц мне бы помогло. Наверное.


 
Fay ©   (2004-04-05 15:40) [15]

А предварительное агрегирование не спасёт отца руской домократии?


 
Fay ©   (2004-04-05 15:40) [16]

"русской" конечно 8)


 
Соловьев ©   (2004-04-05 15:57) [17]


> dimm22   (05.04.04 14:49) [14]

можно поподробнее о структуре и то что хотим получить?


 
Соловьев ©   (2004-04-05 15:58) [18]

ИМХО, временные таблицы спасают тех, кто пересел с фокса и клипера на Оракл. Без временных таблиц можно(нужно) жить :)


 
Fay ©   (2004-04-05 16:04) [19]

Я так заметил, что без мозгов иожно жить. Тока хреново.

2dimm
Давай DDL своих таблов!


 
Fay ©   (2004-04-05 16:11) [20]

execute procedure rashod_sklad_procedure(:prm_data); Не смущает?


 
Fay ©   (2004-04-05 16:15) [21]

Меня - нет 8)


 
dimm22   (2004-04-05 16:21) [22]

Таблица 1 - Deposit. Таблица с приходами товара.
ID_DEP,ID_SKL,ID_INVITEM,ID_GOODS,QUANTITY,DATE...
Таблица 2 - Goods. Таблица с описанием товара (связь по id_goods).
ID_GOODS,ID_TYPE,ID_COD,ART,NAME_R,PRICE_SALE...
Из этих таблиц получаю состояние склада на текущий момент, но основная задача получать состояние склада на любую дату, для этого нужно учитывать расход за период с текущего момента до заданной даты. Эту информацию беру из таблиц:
Таблица 3 - ZAKAZ. Таблица с шапками заказов (по ним товар уходит)
KOD_ZAK,N_YEAR,YEAR_Z,N_ZAK,ID_AVTO,SUM_R,ID_MANAGER...
Таблица 4 - ZDM (товар в заказах, связь по n_zak)
ID_GOODS,QUANTITY,N_ZAK
После данные надо объединить по ID_goods, вот наверное и всё.


 
dimm22   (2004-04-05 16:22) [23]


> execute procedure rashod_sklad_procedure(:prm_data); Не
> смущает?

Извини ошибочка.


 
dimm22   (2004-04-05 16:26) [24]


> dimm22   (05.04.04 16:21) [22]

В табличке 3 ещё дата есть, по которой я и отбираю заказы.


 
Fay ©   (2004-04-05 16:30) [25]

Сэр! Вам знакомо слово "DDL"?


 
dimm22   (2004-04-05 16:46) [26]


> Сэр! Вам знакомо слово "DDL"?

Хотел попонятнее, ну да ладно, получи :-)
CREATE TABLE DEPOSIT (
   ID_DEP       INTEGER NOT NULL,
   ID_SKL       INTEGER,
   ID_INVITEM   INTEGER,
   ID_GOODS     INTEGER,
   QUANTITY     DECIMAL(11,2),
   ID_DEV       SMALLINT,
   ART_DEV      VARCHAR(15),
   QUANT_W      DECIMAL(11,2),
   QUANT_B      DECIMAL(11,2),
   Q_REZERV     DECIMAL(11,2),
   NP           INTEGER,
   PRICE_INV_D  DECIMAL(11,3),
   PRICE_INV_R  DECIMAL(11,2),
   NDS          NUMERIC(5,2),
   Q_INV        DECIMAL(11,2),
   NUMBER_INV   VARCHAR(10),
   GTD          VARCHAR(40),
   COUNTRY      VARCHAR(20),
   PRICE_SALE   DECIMAL(11,2),
   DATA_P       DATE
);

CREATE TABLE GOODS (
   ID_GOODS       INTEGER NOT NULL,
   ID_TYPE        SMALLINT,
   ID_COD         INTEGER,
   ART            VARCHAR(25),
   NAME_R         VARCHAR(45),
   NAME_E         VARCHAR(45),
   WEIGHT         INTEGER,
   TIP            VARCHAR(5),
   "YEAR"         VARCHAR(45),
   NOTE           VARCHAR(60),
   PRICE_KAT      DOUBLE PRECISION,
   PRICE_SALE     DOUBLE PRECISION,
   KOD_SA         SMALLINT,
   NAME_C         VARCHAR(45),
   PRICE_C        NUMERIC(9,2),
   DISCOUNT       NUMERIC(7,2),
   TYPE_DISCOUNT  VARCHAR(20),
   Q_REST         DECIMAL(15,2),
   ART_NEW        VARCHAR(15),
   Q              NUMERIC(9,2),
   Q_REZ          NUMERIC(9,2),
   Q_MOVE         DECIMAL(11,2),
   NAME_LAT       VARCHAR(60),
   ED_LAT         VARCHAR(10),
   SUM_INV        NUMERIC(9,2),
   DATE_DISC_B    DATE,
   DATE_DISC_E    DATE
);

CREATE TABLE ZAKAZ (
   TYPE_DISCOUNT_USL      VARCHAR(30),
   ID_TYPE_PAY            SMALLINT,
   ID_CON                 SMALLINT,
   SHIFT                  SMALLINT,
   DISCOUNT_USL           DOUBLE PRECISION,
   TYPE_DISCOUNT_ZCH      VARCHAR(30),
   DISCOUNT_ZCH           DOUBLE PRECISION,
   N_SF                   INTEGER,
   KURS                   DOUBLE PRECISION,
   ID_CON_TO              INTEGER,
   PR_N                   VARCHAR(20),
   ID_PAYER               SMALLINT,
   TIME_V                 TIME,
   DAT_V                  DATE,
   DOV                    CHAR(150),
   TIME_P                 TIME,
   DATA_P                 DATE,
   KOD_AVT                INTEGER,
   KOD_ZAK                INTEGER,
   N_YEAR                 INTEGER,
   YEAR_Z                 INTEGER,
   N_ZAK                  INTEGER,
   IND_PARTS_OF_KLIENT    DOUBLE PRECISION,
   ID_AVTO                INTEGER,
   DISC_MATER             DOUBLE PRECISION,
   TYPE_DISCOUNT_MATER    VARCHAR(30),
   NOTE1                  VARCHAR(250),
   NOTE2                  VARCHAR(250),
   IND_NDS                SMALLINT,
   IND_NP                 SMALLINT,
   IND_PAY                SMALLINT,
   IND_CLOSE1             SMALLINT,
   DATE_CLOSE_KASSA       DATE,
   TIME_CLOSE_KASSA       TIME,
   IND_CLOSE2             SMALLINT,
   IND_CLOSE3             SMALLINT,
   DATE_OPEN_AFTER_CLOSE  DATE,
   IND1                   SMALLINT,
   PRICE_HOUR             FLOAT,
   CONTACT                VARCHAR(100),
   SUM_PARTS              DOUBLE PRECISION,
   SUM_PARTS_R            DOUBLE PRECISION,
   DATA_USER              DATE,
   TIME_USER              TIME,
   SUM_WORK               DOUBLE PRECISION,
   SUM_WORK_R             DOUBLE PRECISION,
   SUM$                   DOUBLE PRECISION,
   SUM_R                  DOUBLE PRECISION,
   ID_MANAGER             SMALLINT,
   NAME_USER_OPEN         VARCHAR(50),
   NAME_USER_SKLAD        VARCHAR(50),
   NAME_USER_KASSA        VARCHAR(50),
   NAME_USER_PAY          VARCHAR(50),
   ID_USER                SMALLINT,
   OPER_USER              VARCHAR(50),
   NDS                    FLOAT,
   NP                     FLOAT,
   SUM_ITOGO              DOUBLE PRECISION,
   SUM_ITOGO_R            DOUBLE PRECISION,
   SUM_NDS                DOUBLE PRECISION,
   SUM_NDS_PARTS          DOUBLE PRECISION,
   SUM_NDS_WORK           DOUBLE PRECISION,
   SUM_NP                 DOUBLE PRECISION,
   SUM_PARTS_INV          DOUBLE PRECISION,
   SUM_PARTS_INV_R        DOUBLE PRECISION,
   IND                    SMALLINT,
   IND_MOVE               SMALLINT,
   DATA_MOVE              DATE,
   TIME_MOVE              TIME,
   COUNT_CHANGE           SMALLINT,
   DATA_CHANGE            DATE,
   TIME_CHANGE            TIME,
   ID_TYPE_DOC            SMALLINT,
   NUMBER                 INTEGER,
   ADVICE                 BLOB SUB_TYPE 1 SEGMENT SIZE 4096,
   PROBEG                 VARCHAR(100)
);

CREATE TABLE ZDM (
   SUM_INV_R      DOUBLE PRECISION,
   SUM_INV        DOUBLE PRECISION,
   NDS            DOUBLE PRECISION,
   ID_USER        INTEGER,
   SUM_NDS        DOUBLE PRECISION,
   SUM_WO_NDS     DOUBLE PRECISION,
   SUM_PREPAY     DOUBLE PRECISION,
   IND_PREPAY     INTEGER,
   ID_ORDITEM     INTEGER,
   PRICE_NDS      DOUBLE PRECISION,
   PRICE_WO_NDS   DOUBLE PRECISION,
   TYPE_DISCOUNT  VARCHAR(20),
   DISCOUNT       FLOAT,
   DATA_V         DATE,
   QUANT_B        FLOAT,
   QUANT_W        FLOAT,
   TIP            VARCHAR(10),
   ART            VARCHAR(30),
   SUM$           DOUBLE PRECISION,
   PRICE_SALE_R   DOUBLE PRECISION,
   PR             VARCHAR(10),
   ID_GOODS       INTEGER,
   QUANTITY       FLOAT,
   KOL            FLOAT,
   PRICE_SALE     DOUBLE PRECISION,
   ID_DEP         INTEGER,
   N              INTEGER,
   N_ZAK          INTEGER,
   SUM_R          DOUBLE PRECISION,
   NAME_R         VARCHAR(100)
);


 
Fay ©   (2004-04-05 17:01) [27]

Мне всё ясно. Тока чё-то не видно PK тд...


 
stud ©   (2004-04-05 17:26) [28]

а таблицы с шапками обязательно нужны для отображения?
в каком виде должен получиться отчет?
если в виде:
товар , приход , расход , остаток(на дату)


 
dimm22   (2004-04-05 17:31) [29]


> товар , приход , расход , остаток(на дату)

Приблизительно так и надо.


 
Соловьев ©   (2004-04-05 17:34) [30]

читал-читал, не догнал что нужно :)
Можно кокретно, такие поля нужны в таких-то таблицах. Или все поля нужны?


 
stud ©   (2004-04-05 17:42) [31]

так тогда на кой тут шапки???
по идее выборка должна быть из 3-х таблиц.
справочника товаров, расхода товаров, прихода товаров.
а это уже проще.))


 
dimm22   (2004-04-05 17:46) [32]

В [22] я всё описал. А нужен отчёт остаток товара(на дату).
Поля нужны ART,NAME_R,PRICE_SALE из Goods, колличество на заданную дату и расход за период с заданного дня до текущего момента.


 
stud ©   (2004-04-05 17:52) [33]

ну примерно мне кажется должно быть так
for select (нужные поля) from (справочник товаров)
do
begin
select (нужные роля) from (таблица приходов)
select (нужные поля) from (таблица расходов)
suspend
end
ну а сложить приход с расходом, чтобы получить остаток наверное не сложно



Страницы: 1 вся ветка

Текущий архив: 2004.05.02;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.024 c
1-1081864133
Viking
2004-04-13 17:48
2004.05.02
Вопрос по работе с Delphi Open Tools Api


7-1078480371
visualman
2004-03-05 12:52
2004.05.02
Срочно нужен ДОК


4-1078595459
Shopot
2004-03-06 20:50
2004.05.02
WinAPI. Ring-0.


14-1081621713
Yanis
2004-04-10 22:28
2004.05.02
Худое окно


4-1078477390
Amirka
2004-03-05 12:03
2004.05.02
Запретить printscreen