Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2004.05.02;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.036 c
1-1081834667
MikePol
2004-04-13 09:37
2004.05.02
Проблема с потоками


8-1074041218
Валентин
2004-01-14 03:46
2004.05.02
TAG в mp3


14-1081608838
SergeySh
2004-04-10 18:53
2004.05.02
Диск к книге DirectX (графика в проектах), автор - Михаил Краснов


1-1082024944
Ivolg
2004-04-15 14:29
2004.05.02
Компонент Exel


1-1081958058
DarkSet
2004-04-14 19:54
2004.05.02
Защита файлов от доступа





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский