запрос с использованием group by

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

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

Ответить
aaa3d
Сообщения: 69
Зарегистрирован: 23 ноя 2005, 11:06

запрос с использованием group by

Сообщение aaa3d » 12 апр 2006, 11:38

сразу извиняюсь что длинно получилось - но посторался сразу все написать - горит проблема
есть таблица учета товара от всех проводок (приходы, расходы, списания,....)

в таблице 800 000 записей
складов 10
живых товаров 6000

по товару 9159 - 7000 записей (самый частый)

select * from reg where dt between "03/01/2006" and "03/02/2006" and tW_id=9159 - выдает 15 записей

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

CREATE TABLE REG (
    TW_ID    ID /* ID = INTEGER NOT NULL */, товар
    SHOP_ID  ID /* ID = INTEGER NOT NULL */, магазин
    SKL_ID   ID /* ID = INTEGER NOT NULL */, склад
    DT       DATE, дата 
    TW_KOL   FLOAT, количество товара
    ID       ID /* ID = INTEGER NOT NULL */,
    TYP      ID /* ID = INTEGER NOT NULL */,
    FRM_ID   ID /* ID = INTEGER NOT NULL */
);

CREATE INDEX REG_DT ON REG (DT);
CREATE INDEX REG_FRM ON REG (FRM_ID);
CREATE INDEX REG_ID ON REG (ID);
CREATE INDEX REG_IDX1 ON REG (TW_ID, TW_KOL);
CREATE INDEX REG_IDX2 ON REG (SKL_ID, DT);
ALTER INDEX REG_IDX2 INACTIVE;
CREATE INDEX REG_SHOP ON REG (SHOP_ID);
CREATE INDEX REG_SKL ON REG (SKL_ID);
CREATE INDEX REG_TW ON REG (TW_ID);
CREATE INDEX REG_TWID_SKLID ON REG (TW_ID, SKL_ID);
CREATE INDEX REG_TW_DT ON REG (TW_ID, DT);
CREATE INDEX REG_TW_SKL ON REG (TW_ID, SKL_ID, FRM_ID);
CREATE INDEX REG_TYP ON REG (TYP);
CREATE INDEX REG_TYP_ID ON REG (TYP, ID);

надо получить количество товара 9159 за период за 1 день в течении месяца
с разбивкой по складам

запрос: select sum(tw_kol), skl_id from reg where
tw_id=9159 and dt between "03/01/2006" and "03/02/2006"
group by skl_id

PLAN (REG ORDER REG_SKL)

один раз этот запрос выполняется моментально. но мне его надо строить 30 раз (за месяц).
30 кратное выполнение занимает 2 секунды - дофига, учитывая что отчет надо строить по 50000 товаров.

как не пытаюсь индексами играть, не ускоряется :(

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




статистика
1 раз
Prepare : 0.00 ms
Execute : 63.00 ms
Avg fetch time: 12.60 ms
Read : 295
Writes : 0
Fetches: 781
+--------------------------+-----------+-----------+-------------+---------+---------+---------+
| Table Name | Records | Indexed | Non-Indexed | Updates | Deletes | Inserts |
| | Total | reads | reads | | | |
+--------------------------+-----------+-----------+-------------+---------+---------+---------+
| REG| 0 | 161 | 0 | 0 | 0 | 0 |
+--------------------------+-----------+-----------+-------------+---------+---------+---------+

20 раз
Prepare : 0.00 ms
Execute : 1 063.00 ms
Avg fetch time: 10.63 ms
Read : 0
Writes : 2
Fetches: 6 930


+--------------------------+-----------+-----------+-------------+---------+---------+---------+
| Table Name | Records | Indexed | Non-Indexed | Updates | Deletes | Inserts |
| | Total | reads | reads | | | |
+--------------------------+-----------+-----------+-------------+---------+---------+---------+
| REG| 0 | 300 | 0 | 0 | 0 | 0 |
| SKL| 0 | 0 | 20 | 0 | 0 | 0 |
+--------------------------+-----------+-----------+-------------+---------+---------+---------+

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

Сообщение kdv » 12 апр 2006, 13:12

один раз этот запрос выполняется моментально. но мне его надо строить 30 раз (за месяц).
ну и сохраняй промежуточный результат. кто не дает???

aaa3d
Сообщения: 69
Зарегистрирован: 23 ноя 2005, 11:06

Сообщение aaa3d » 12 апр 2006, 13:18

ммм, непонятно написал :)
промежуточных результатов у меня нет,

если упрощенно.....
30 раз строить - это значить что строю отчет средний остаток товара за месяц :)
т.е. получаю остатки товара на каждый день и потом делю на 30.

если не использовать группировку - все ок.
если делать вместо
select sum(tw_kol), skl_id from reg where
tw_id=9159 and dt between "03/01/2006" and "03/02/2006"
group by skl_id

такое
for select skl_id from skl into :skl_id do
select sum(tw_kol), skl_id from reg where
tw_id=9159 and dt between "03/01/2006" and "03/02/2006"
and skl_id=:skl_id

то время отработки доли секунды.

но некрасиво както. grouup by вроде более разумный вариант, но че то он неспешно работает :(

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

Сообщение kdv » 12 апр 2006, 13:30

промежуточных результатов у меня нет,
значит сделай. у тебя на каждый день остаток фиксирован? Тогда зачем его пересчитывать каждый раз?
grouup by вроде более разумный вариант, но че то он неспешно работает
потому что план для группировки использует индекс по order. я про это писал тут:
http://www.sql.ru/forum/actualthread.as ... =2#2535391

в случае отсуствия group by строится совершенно другой план.

aaa3d
Сообщения: 69
Зарегистрирован: 23 ноя 2005, 11:06

Сообщение aaa3d » 12 апр 2006, 14:01

Спасибо!!!!!
в твоем посте нашел то что меня спасает :))
сам че то недопетрил как сделать группировку без индекса

мне нужно select skl_id+0..... group by 1



мне именно это и надо было.
Еще раз баальшое спасибо

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

Сообщение kdv » 12 апр 2006, 14:25

все равно рекомендую озаботиться хранением промежуточных агрегатов.

Ответить