Помогите оптимизировать запрос: sel*fr x where v=(sel min(v)

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

Ответить
xvv
Сообщения: 21
Зарегистрирован: 23 май 2008, 07:33

Помогите оптимизировать запрос: sel*fr x where v=(sel min(v)

Сообщение xvv » 07 авг 2008, 11:54

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

select * from zaivka skv1, zaivka_status ss1
               where ss1.id=skv1.sost and ss1.otboy='F'
                 and SKV1.in_d+skv1.id_t/24=(select min(a.in_d+a.id_t/24)
                                               from zaivka a, zaivka_status ss3
                                              where ss3.id=a.sost
                                                and ss3.otboy='F'
                                                and a.in_d>=:dd
                                                and a.KV=skv1.KV)
zaivka_status - маленькая (30 записей)
zaivka - несколько миллионов.

Ненравится сам запрос. Но как передалать - никак не соображу.

Tonal
Сообщения: 104
Зарегистрирован: 30 сен 2007, 13:42

Сообщение Tonal » 07 авг 2008, 12:51

Какой сервер? По каким полям индексы? И какой план получается?

xvv
Сообщения: 21
Зарегистрирован: 23 май 2008, 07:33

Сообщение xvv » 07 авг 2008, 13:09

fb 2.1
План
PLAN JOIN (A INDEX (ZAIVKA_IDX1), SS3 INDEX (RDB$PRIMARY14))
PLAN JOIN (SS1 NATURAL, SKV1 INDEX (ZAIVKA_IDX3))

Адаптированный план
PLAN JOIN (A INDEX (ZAIVKA_IDX1), SS3 INDEX (PK_ZAIVKA_STATUS)) PLAN JOIN (SS1 NATURAL, SKV1 INDEX (ZAIVKA_IDX3))

------ Performance info ------
Prepare time = 0ms
Execute time = 281ms
Avg fetch time = 12,77 ms
Current memory = 20 232 716
Max memory = 40 927 740
Memory buffers = 2 048
Reads from disk to cache = 6 887
Writes from cache to disk = 0
Fetches from cache = 571 436

ALTER TABLE ZAIVKA ADD CONSTRAINT PK_ZAIVKA PRIMARY KEY (ID);
CREATE UNIQUE INDEX ZAIVKA_IDX1 ON ZAIVKA (KV, IN_D, ID_T, OUT_D, OUT_T, ID);
CREATE INDEX ZAIVKA_IDX2 ON ZAIVKA (KLIENT_SRT);
CREATE INDEX ZAIVKA_IDX3 ON ZAIVKA (SOST, IN_D, ID_T, OUT_D, OUT_T);

Но мне сама конструкция ненравится.
и то что запрос возвращает 100 записей, а чтений 100.000....

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 07 авг 2008, 13:20

Зачем у тебя запрос коррелированный?
Ты по каждому KV отдельно минимум находишь?

xvv
Сообщения: 21
Зарегистрирован: 23 май 2008, 07:33

Сообщение xvv » 07 авг 2008, 14:08

да. Мне по каждой KV нужно найти 1 заявку.

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 07 авг 2008, 15:35

Одну? Ну так это меняет дело. Эта самая, которая минимальная, сойдёт?
А то твой запрос находит ВСЕ заявки для данного KV, равные найденному, причём уже без условия in_d>=:dd

Вообще, я бы тебе рекомендовал процедуру написать, а не запросом получать.

xvv
Сообщения: 21
Зарегистрирован: 23 май 2008, 07:33

Сообщение xvv » 07 авг 2008, 15:54

Одну или null строк для каждого kv.
про сам запрос - мог бы, но не вернёт - больше нет (проверка в тригере на таблице специально стоит, чтоб такого не случилось).

Tonal
Сообщения: 104
Зарегистрирован: 30 сен 2007, 13:42

Сообщение Tonal » 08 авг 2008, 15:52

Можно попробовать через CTE.
Например так:

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

with
  cte as (
    select * from zaivka skv1, zaivka_status ss1
    where ss1.id=skv1.sost and ss1.otboy='F' and skv1.in_d>=:dd)
select * from cte cte1
where cte1.in_d+cte1.id_t/24=(
  select min(cte2.in_d+cte2.id_t/24)
  from cte cte2 where cte2.KV=cte1.KV)

Ответить