Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Оптимизация запроса [D7]


Страницы:   1 2

McSimm2 ©   (2003-07-15 08:46:00) 

Есть запрос один-ко-многим, который в свою очередь то же является запросом один-ко многим. Всё усугубляется тем, что в конечном итоге это ещё и в тройном экземпляре...


SELECT s.*, kv.*
FROM sobes_analiz s,
(SELECT k.rajon, k.jeu, k.n_lc, k.ulica, k.dom, k.kvart, k.p_kom,
k.famil, k.kkom, v.famil AS vfamil, v.imj AS vimj,
v.otch AS votch
FROM (SELECT *
FROM ksm k2
WHERE ( (k2.kkom <> "5")
AND (k2.kkom <> "7")
AND (k2.kkom <> "8")
AND (k2.kkom <> "9")
)
OR k2.kkom IS NULL) k,
vet v
WHERE ((k.jeu = v.jeu(+))
AND (k.rajon = v.rajon(+))
AND (k.n_lc = v.n_lc(+)))) kv

WHERE (( s.ksmstreet = kv.ulica(+)
AND s.ksmhouse = kv.dom(+)
AND NVL (s.ksmflat, -1) = NVL (kv.kvart(+), -1)
)
)
UNION
SELECT s.*, kv.*
FROM sobes_analiz s,
(SELECT k.rajon, k.jeu, k.n_lc, k.ulica, k.dom, k.kvart, k.p_kom,
k.famil, k.kkom, f.famil AS vfamil, "" AS vimj, "" AS votch
FROM (SELECT *
FROM ksm_ved k2
WHERE ( (k2.kkom <> "5")
AND (k2.kkom <> "7")
AND (k2.kkom <> "8")
AND (k2.kkom <> "9")
)
OR k2.kkom IS NULL) k,
vet_ved f
WHERE ((k.jeu = f.jeu(+))
AND (k.rajon = f.rajon(+))
AND (k.n_lc = f.n_lc(+)))) kv
WHERE (( s.ksmstreet = kv.ulica(+)
AND s.ksmhouse = kv.dom(+)
AND NVL (s.ksmflat, -1) = NVL (kv.kvart(+), -1)
)
)
UNION
SELECT s.*, kv.*
FROM sobes_analiz s,
(SELECT k.rajon, k.jeu, k.n_lc, k.ulica, k.dom, k.kvart, 0, k.famil, "",
f.famil AS vfamil, "" AS vimj, "" AS votch
FROM ksm_chs k, vet_chs f
WHERE ((k.jeu = f.jeu(+))
AND (k.rajon = f.rajon(+))
AND (k.n_lc = f.n_lc(+)))) kv
WHERE (( s.ksmstreet = kv.ulica(+)
AND s.ksmhouse = kv.dom(+)
AND NVL (s.ksmflat, -1) = NVL (kv.kvart(+), -1)
)
)



Причём кусок запроса


SELECT k.rajon, k.jeu, k.n_lc, k.ulica, k.dom, k.kvart, k.p_kom,
k.famil, k.kkom, v.famil AS vfamil, v.imj AS vimj,
v.otch AS votch
FROM (SELECT *
FROM ksm k2
WHERE ( (k2.kkom <> "5")
AND (k2.kkom <> "7")
AND (k2.kkom <> "8")
AND (k2.kkom <> "9")
)
OR k2.kkom IS NULL) k,
vet v
WHERE ((k.jeu = v.jeu(+))
AND (k.rajon = v.rajon(+))
AND (k.n_lc = v.n_lc(+)))

Этот кусок отрабатывается меньше секунды, а уже если его использовать в общем запросе, то 3 минуты. Весь запрос работает минут 7.

База Ksm - 180.000 записей, Vet - 450.000. Все остальные - мелкие - порядка 10.000

Мастера, как запрос соптимизировать можно ?


Dan   (2003-07-15 09:45:00) [21]

елки-моталки, а если попробовать сделать сначала 3 юниона, потом уже соединять полученное множество с таблицей sobes_analiz.


Sergey13   (2003-07-15 09:43:00) [22]

2McSimm2 (15.07.03 09:25)
А планы то смотрел? Что они показывают?
>Индексы сделаны - по всем таблицам
С NVL они работать скорее всего не будут. Смотри планы выполнения. Хотя это видно и по скорости выполнения которые ты привел.

>Как можно от NVL (s.ksmflat, -1) = NVL (kv.kvart(+), -1)избавиться? Для моей задачи именно NVL и нужен , что бы можно было коннектить по полям если значение null в них

Я предлагал изменить структуру данных - если это возможно. Если в этих полях не нужны NULL, то и избавься от них раз и навсегда.

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

>WHERE ( (k2.kkom <> "5")
AND (k2.kkom <> "7")
AND (k2.kkom <> "8")
AND (k2.kkom <> "9")
)
Вот эту часть попробовать сделать через равенство а не через неравенство. Ускоряет иногда, за счет лучшего использования индекса. Или можно попробовать переделать на NOT IN (5,7,8,9).

Да дофига вариантов. Оптимизация - дело тонкое.


Dan   (2003-07-15 09:41:00) [23]

там есть, но не помню где :-(( просто я пользуюсь SQL Navigator.
Должно быть что-то вроде Explain plan tool


McSimm2   (2003-07-15 09:36:00) [24]

Dan (15.07.03 09:34)
Как это можно осуществить и где ? Пользуюсь Toad`ом


Johnmen   (2003-07-15 09:34:00) [25]

1.Весь этот немыслимый запрос можно переписать так, чтобы не было "запрос из запроса", а лишь соединение таблиц, хоть и левое.
2.Серьезно и вдумчиво подойти к проектированию БД. Чтобы не было мучительно больно в ожидании выполнения многоэтажных запросов...:)


Dan   (2003-07-15 09:34:00) [26]

план выполнения запроса смотрел ??? чего он рисует ?


McSimm2   (2003-07-15 09:28:00) [27]

Dan (15.07.03 09:25)

Индексы стоят так:
по sobes_analiz стоит ksmstreet,ksmhouse,ksmflat
по vet,vetchs,vetved - jeu,rajon,n_lc
по ksm,ksmchs,ksmved - jeu,rajon,n_lc
7 индексов итого - вроде никакие не пересекаются


McSimm2   (2003-07-15 09:25:00) [28]

passm © (15.07.03 09:23)

[Oracle]


Dan   (2003-07-15 09:25:00) [29]

а ты построй 2 индекса по выражениям NVL (s.ksmflat, -1) и NVL (kv.kvart, -1)


McSimm2   (2003-07-15 09:25:00) [30]

Dan (15.07.03 09:17)
Unioon all я ставил - скорость увеличивается, но не намного.
Конкретно по работе отдельных кусков, как предлогал
Sergey13 © (15.07.03 09:09)

получается, что

SELECT k.rajon, k.jeu, k.n_lc, k.ulica, k.dom, k.kvart, k.p_kom,
k.famil, k.kkom, v.famil AS vfamil, v.imj AS vimj,
v.otch AS votch
FROM (SELECT *
FROM ksm k2
WHERE ( (k2.kkom <> "5")
AND (k2.kkom <> "7")
AND (k2.kkom <> "8")
AND (k2.kkom <> "9")
)
OR k2.kkom IS NULL) k,
vet v
WHERE ((k.jeu = v.jeu(+))
AND (k.rajon = v.rajon(+))
AND (k.n_lc = v.n_lc(+)))


работает 16 милисекунд, а


sELECT s.*, kv.*
FROM sobes_analiz s,
(SELECT k.rajon, k.jeu, k.n_lc, k.ulica, k.dom, k.kvart, k.p_kom,
k.famil, k.kkom, v.famil AS vfamil, v.imj AS vimj,
v.otch AS votch
FROM (SELECT *
FROM ksm k2
WHERE ( (k2.kkom <> "5")
AND (k2.kkom <> "7")
AND (k2.kkom <> "8")
AND (k2.kkom <> "9")
)
OR k2.kkom IS NULL) k,
vet v
WHERE ((k.jeu = v.jeu(+))
AND (k.rajon = v.rajon(+))
AND (k.n_lc = v.n_lc(+)))) kv

WHERE (( s.ksmstreet = kv.ulica(+)
AND s.ksmhouse = kv.dom(+)
AND NVL (s.ksmflat, -1) = NVL (kv.kvart(+), -1)
)
)


отрабатывает хорошо за 3 минуты


passm   (2003-07-15 09:23:00) [31]

McSimm2 (15.07.03 08:46)> СУБД?


McSimm2   (2003-07-15 09:20:00) [32]

Индексы сделаны - по всем таблицам; Каждый кусок я отрабытаю - в вопросе я это и описал.
Как можно от NVL (s.ksmflat, -1) = NVL (kv.kvart(+), -1)избавиться? Для моей задачи именно NVL и нужен , что бы можно было коннектить по полям если значение null в них


Dan   (2003-07-15 09:17:00) [33]

если нет цели убрать повторяющиеся строки , может попробовать поставить UNION ALL.


Sergey13   (2003-07-15 09:09:00) [34]

2McSimm2 (15.07.03 08:46)
1.Попробуй избавиться от конструкций типа
NVL (s.ksmflat, -1) = NVL (kv.kvart(+), -1)
Если тебе надо по умолчанию -1 то так и сделай.
2.Отрабатывай каждый "кусок" отдельно. Планчики смотри.
3.Попробуй хинтами пользоваться.
4.Попробуй сделать вьюху по твоему подзапросу.
5.Индексы
6.Статистику собираешь?
n-1. Вопросы у тебя, однако. Тут до хрена чего можно крутить. 8-)


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо