Форум: "Базы";
Текущий архив: 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.058 c