[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Оптимизировать запрос для крутых ;)
vital
Досталась вот мне в наследство одна бд.. Есть таблица, и к ней написал запрос..
SELECT DISTINCT a.item_value as director,
c.item_value as code,
d.item_value as raion,
e.item_value as nazvanie,
f.item_value as hzchto3,
g.item_value as nomer,
h.item_value as hzchto2,
i.item_value as vid,
k.item_value as tip,
l.item_value as finansirovanie,
m.item_value as orgforma,
n.item_value as podchinenie,
o.item_value as okrug,
p.item_value as hzchto1
from KF_ATTR_VALUE a
left join KF_ATTR_VALUE b on a.obj_id=b.obj_id
left join KF_ATTR_VALUE c on a.obj_id=c.obj_id
left join KF_ATTR_VALUE d on a.obj_id=d.obj_id
left join KF_ATTR_VALUE e on a.obj_id=e.obj_id
left join KF_ATTR_VALUE f on a.obj_id=f.obj_id
left join KF_ATTR_VALUE g on a.obj_id=g.obj_id
left join KF_ATTR_VALUE h on a.obj_id=h.obj_id
left join KF_ATTR_VALUE i on a.obj_id=i.obj_id
left join KF_ATTR_VALUE k on a.obj_id=k.obj_id
left join KF_ATTR_VALUE l on a.obj_id=l.obj_id
left join KF_ATTR_VALUE m on a.obj_id=m.obj_id
left join KF_ATTR_VALUE n on a.obj_id=n.obj_id
left join KF_ATTR_VALUE o on a.obj_id=o.obj_id
left join KF_ATTR_VALUE p on a.obj_id=p.obj_id
where
a.attr_id=186
and c.attr_id = 167
and d.attr_id = 168
and e.attr_id = 190
and f.attr_id = 199
and g.attr_id = 203
and h.attr_id = 211
and i.attr_id = 212
and k.attr_id = 213
and l.attr_id = 214
and m.attr_id = 215
and n.attr_id = 216
and o.attr_id = 217
and p.attr_id = 425

Может можно это как-то по лучше?)
===
update:
Цитата (Oyeme @ 28.03.2012 - 21:40)
Что Вам говорит об этом запросе EXPLAIN ?

Что Вы хотите сделать для начало объясните.. ;)
Выглядит извращением. :)

Есть табличка с набором атрибутов объекта.
примерно:
attr_id|obj_id|item_value
1------|1------|свойство1
2------|1------|свойство2
3------|1------|свойтво3
1------|2------|свойство1
2------|2------|свойство2
3------|2------|свойтво3

Именно в таком виде и менять нельзя.
Нужно вытащить ряд атрибутов - 13 - для каждого объекта(т.е. сделать таблицу) - их id в where и обозначены.
И запрос это делает. Нужно вот это как-то аккуратнее написать, если возможно.



Спустя 13 минут, 25 секунд (28.03.2012 - 22:40) Oyeme написал(а):
Что Вам говорит об этом запросе EXPLAIN ?

Что Вы хотите сделать для начало объясните.. wink.gif
Выглядит извращением. smile.gif

Спустя 8 минут, 9 секунд (28.03.2012 - 22:48) vital написал(а):
Цитата (Oyeme @ 28.03.2012 - 21:40)
Что Вам говорит об этом запросе EXPLAIN ?

Что Вы хотите сделать для начало объясните.. wink.gif
Выглядит извращением. smile.gif

Есть табличка с набором атрибутов объекта.
примерно:
attr_id|obj_id|item_value
1------|1------|свойство1
2------|1------|свойство2
3------|1------|свойтво3
1------|2------|свойство1
2------|2------|свойство2
3------|2------|свойтво3

Именно в таком виде и менять нельзя.
Нужно вытащить ряд атрибутов - 13 - для каждого объекта(т.е. сделать таблицу) - их id в where и обозначены.
И запрос это делает. Нужно вот это как-то аккуратнее написать, если возможно.

Спустя 5 минут, 5 секунд (28.03.2012 - 22:53) vital написал(а):
EXPLAIN експортированный в CSV ниже. И да - БД Oracle
OPERATION OPTIONS OBJECT_NAME POSITION
"SELECT STATEMENT" (null) (null) 1738579
" HASH" "UNIQUE" (null) 1
" HASH JOIN" (null) (null) 1
" TABLE ACCESS" "BY INDEX ROWID" "KF_ATTR_VALUE" 1
" INDEX" "RANGE SCAN" "KF_ATTR_VALUE_FK1" 1
" HASH JOIN" (null) (null) 2
" TABLE ACCESS" "BY INDEX ROWID" "KF_ATTR_VALUE" 1
" INDEX" "RANGE SCAN" "KF_ATTR_VALUE_FK1" 1
" HASH JOIN" (null) (null) 2
" TABLE ACCESS" "BY INDEX ROWID" "KF_ATTR_VALUE" 1
" INDEX" "RANGE SCAN" "KF_ATTR_VALUE_FK1" 1
" HASH JOIN" (null) (null) 2
" TABLE ACCESS" "BY INDEX ROWID" "KF_ATTR_VALUE" 1
" INDEX" "RANGE SCAN" "KF_ATTR_VALUE_FK1" 1
" HASH JOIN" "RIGHT OUTER" (null) 2
" INDEX" "FAST FULL SCAN" "KF_ATTR_VALUE_FK2" 1
" HASH JOIN" (null) (null) 2
" TABLE ACCESS" "BY INDEX ROWID" "KF_ATTR_VALUE" 1
" INDEX" "RANGE SCAN" "KF_ATTR_VALUE_FK1" 1
" HASH JOIN" (null) (null) 2
" TABLE ACCESS" "BY INDEX ROWID" "KF_ATTR_VALUE" 1
" INDEX" "RANGE SCAN" "KF_ATTR_VALUE_FK1" 1
" HASH JOIN" (null) (null) 2
" TABLE ACCESS" "BY INDEX ROWID" "KF_ATTR_VALUE" 1
" INDEX" "RANGE SCAN" "KF_ATTR_VALUE_FK1" 1
" HASH JOIN" (null) (null) 2
" TABLE ACCESS" "BY INDEX ROWID" "KF_ATTR_VALUE" 1
" INDEX" "RANGE SCAN" "KF_ATTR_VALUE_FK1" 1
" HASH JOIN" (null) (null) 2
" TABLE ACCESS" "BY INDEX ROWID" "KF_ATTR_VALUE" 1
" INDEX" "RANGE SCAN" "KF_ATTR_VALUE_FK1" 1
" HASH JOIN" (null) (null) 2
" TABLE ACCESS" "BY INDEX ROWID" "KF_ATTR_VALUE" 1
" INDEX" "RANGE SCAN" "KF_ATTR_VALUE_FK1" 1
" HASH JOIN" (null) (null) 2
" TABLE ACCESS" "BY INDEX ROWID" "KF_ATTR_VALUE" 1
" INDEX" "RANGE SCAN" "KF_ATTR_VALUE_FK1" 1
" HASH JOIN" (null) (null) 2
" TABLE ACCESS" "BY INDEX ROWID" "KF_ATTR_VALUE" 1
" INDEX" "RANGE SCAN" "KF_ATTR_VALUE_FK1" 1
" HASH JOIN" (null) (null) 2
" TABLE ACCESS" "BY INDEX ROWID" "KF_ATTR_VALUE" 1
" INDEX" "RANGE SCAN" "KF_ATTR_VALUE_FK1" 1
" TABLE ACCESS" "BY INDEX ROWID" "KF_ATTR_VALUE" 2
" INDEX" "RANGE SCAN" "KF_ATTR_VALUE_FK1" 1

Спустя 30 минут, 3 секунды (28.03.2012 - 23:23) Placido написал(а):
Жесть ))) Не уверен, но как вам такой вариант:
SELECT GROUP_CONCAT(DISTINCT item_value)
FROM KF_ATTR_VALUE
WHERE attr_id IN (167,168,186,190,199,203,211,212,213,214,215,216,217,425)
GROUP BY obj_id;

Каждую строку результата разбивать с помощью exlode(), после чего в массиве будут лежать значения, соответствующие полям code, raion, director, nazvanie, hzchto3, nomer, hzchto2, vid, tip, finansirovanie, orgforma, podchinenie, okrug,hzchto1 (ключи от 0 до 13) для соответствующего obj_id.
Изврат, конечно, но все же.

Спустя 11 часов, 46 минут, 31 секунда (29.03.2012 - 11:10) vital написал(а):
В оракле нету group_concat smile.gif
Есть замены на pl/sql, но я не так крут ;(

Спустя 14 минут, 14 секунд (29.03.2012 - 11:24) Placido написал(а):
Я с Ораклом не сталкивался, но нашел, что там есть подобная GROUP_CONCAT функция WM_CONCAT, но это зависит от версии сервера.

Спустя 15 минут, 50 секунд (29.03.2012 - 11:40) Игорь_Vasinsky написал(а):
Свернутый текст
о боже blink.gif

Спустя 5 часов, 56 минут, 55 секунд (29.03.2012 - 17:36) vital написал(а):
Чем дальше в лес, тем круче:
SELECT    a.obj_id as id, a.item_value as director,
b.uchreditel, c.sokr_name, d.pop_sov,
e.upr_sov, f.obr_process,g.proezd,
h.primechanie
from KF_ATTR_VALUE a

left join (
select z.ITEM_VALUE as uchreditel, z.obj_id as id
from KF_ATTR_VALUE z
where z.obj_id=obj_id and z.attr_id = 197) b
on b.id = a.obj_id
left join (
select z.ITEM_VALUE as sokr_name, z.obj_id as id
from KF_ATTR_VALUE z
where z.obj_id=obj_id and z.attr_id = 185) c
on c.id = a.obj_id
left join (
select z.ITEM_VALUE as pop_sov, z.obj_id as id
from KF_ATTR_VALUE z
where z.obj_id=obj_id and z.attr_id = 201) d
on d.id = a.obj_id
left join (
select z.ITEM_VALUE as upr_sov, z.obj_id as id
from KF_ATTR_VALUE z
where z.obj_id=obj_id and z.attr_id = 202) e
on e.id = a.obj_id
left join (
select z.ITEM_VALUE as obr_process, z.obj_id as id
from KF_ATTR_VALUE z
where z.obj_id=obj_id and z.attr_id = 199) f
on f.id = a.obj_id
left join (
select z.ITEM_VALUE as proezd, z.obj_id as id
from KF_ATTR_VALUE z
where z.obj_id=obj_id and z.attr_id = 210) g
on g.id = a.obj_id
left join (
select z.ITEM_VALUE as primechanie, z.obj_id as id
from KF_ATTR_VALUE z
where z.obj_id=obj_id and z.attr_id = 211) h
on h.id = a.obj_id

where
a.attr_id = 186
and a.obj_id = $this->OBJ_ID

Потом вот это вот должно будет выдерживать 20к юзверей в день(не одновременно.. надеюсб) по тз)

Спустя 5 минут, 4 секунды (29.03.2012 - 17:42) vital написал(а):
ПОдскажет кто - если взять запрос выше и переписать в виде:
SELECT distinct
(SELECT ITEM_VALUE FROM kf_attr_value z WHERE z.obj_id=449 and z.attr_id = 197) uchreditel,
(
SELECT ITEM_VALUE FROM kf_attr_value z WHERE z.obj_id=449 and z.attr_id = 168) raion from kf_attr_value

..и тп.
Разница в скорости будет заметна? ЧТо быстрее подзапрос или джоин?

Спустя 5 часов, 28 минут, 13 секунд (29.03.2012 - 23:10) I++ написал(а):
20к юзверей в день в режиме онлайн? Нагрузки предположительные известны?

В первом запросе и так все нормально. Если конечно 20к пользователей в режиме онлайн, на пентиуме 2, то все умрет в муках.

Помню трафико-счеталку делал, для тех, у кого денег на сиску нет. Ну она нормально держала по 1 ляму запросов в день на MySQL, на Core 2 Duo, нагрузка 45% проца biggrin.gif

Спустя 1 день, 19 часов, 22 минуты, 12 секунд (31.03.2012 - 18:32) Лена написал(а):
Цитата (vital @ 29.03.2012 - 14:42)
ЧТо быстрее подзапрос или джоин?

Я не специалист по Оракл, сама сейчас книгу по нему читаю. По работе часто сталкиваюсь, у нас одна компания на Оракле работает. То, что дальше, сообщаю не как догму, а как личные наблюдения. Они джойны редко используют, мне говорили, что сильно тормозят, подзапросы быстрее, и составные индексы надо обязательно ставить на полях, которые в подзапросе попадают в WHERE.

Спустя 43 минуты, 11 секунд (31.03.2012 - 19:15) glock18 написал(а):
Цитата (vital @ 29.03.2012 - 08:10)
В оракле нету group_concat


чем это мешает то? или Вам проще выполнять запрос с кучей джойнов, чем разобрать 15 строк результатов однотабличного запроса?

Спустя 38 минут, 32 секунды (31.03.2012 - 19:54) sergeiss написал(а):
Смотрел я на этот запрос, смотрел... И всё не пойму никак. Зачем ДЖОЙНы-то? Узнал про них и решил использовать?
Я правильно понял запрос? Надо для всех obj_id из таблицы KF_ATTR_VALUE выбрать набор атрибутов с определенными номерами?

Можно так попробовать, с использованием специфики Оракла:
WITH
obj_ids AS (SELECT distinct obj_id FROM KF_ATTR_VALUE)

SELECT

(SELECT item_value FROM KF_ATTR_VALUE WHERE obj_id=obj_list.obj_id AND attr_id=186) as director,
(
SELECT item_value FROM KF_ATTR_VALUE WHERE obj_id=obj_list.obj_id AND attr_id=167) as code,
(
SELECT item_value FROM KF_ATTR_VALUE WHERE obj_id=obj_list.obj_id AND attr_id=168) as raion,
(
SELECT item_value FROM KF_ATTR_VALUE WHERE obj_id=obj_list.obj_id AND attr_id=190) as nazvanie

FROM obj_ids obj_list

order by obj_id


Я взял только первые 4 атрибута. Если все заработает, то тогда можно будет и другие атрибуты добавить :)
Если надо ограничить количество obj_id, то сделать это можно в самом первом запросе, которые идет сразу же после WITH. Пишешь там или условие WHERE или ограничение LIMIT.

При правильно сделанных индексах запрос должен просто "летать".

Спустя 16 часов, 14 минут, 51 секунда (1.04.2012 - 12:09) vital написал(а):
Цитата (sergeiss @ 31.03.2012 - 18:54)
Смотрел я на этот запрос, смотрел... И всё не пойму никак. Зачем ДЖОЙНы-то? Узнал про них и решил использовать?
Я правильно понял запрос? Надо для всех obj_id из таблицы KF_ATTR_VALUE выбрать набор атрибутов с определенными номерами?

Можно так попробовать, с использованием специфики Оракла:
WITH
obj_ids AS (SELECT distinct obj_id FROM KF_ATTR_VALUE)

SELECT

(SELECT item_value FROM KF_ATTR_VALUE WHERE obj_id=obj_list.obj_id AND attr_id=186) as director,
(
SELECT item_value FROM KF_ATTR_VALUE WHERE obj_id=obj_list.obj_id AND attr_id=167) as code,
(
SELECT item_value FROM KF_ATTR_VALUE WHERE obj_id=obj_list.obj_id AND attr_id=168) as raion,
(
SELECT item_value FROM KF_ATTR_VALUE WHERE obj_id=obj_list.obj_id AND attr_id=190) as nazvanie

FROM obj_ids obj_list

order by obj_id


Я взял только первые 4 атрибута. Если все заработает, то тогда можно будет и другие атрибуты добавить :)
Если надо ограничить количество obj_id, то сделать это можно в самом первом запросе, которые идет сразу же после WITH. Пишешь там или условие WHERE или ограничение LIMIT.

При правильно сделанных индексах запрос должен просто "летать".

Скорее просто шел поток мысли как вытащить данные правильно.
Из списка сделать колонки - проще всего джоинить саму в себя. Ну и потом селекты добавились в потоке мысли.
А потом, написав, подумал что
Цитата
Одскажет кто - если взять запрос выше и переписать в виде:

SELECT distinct
(SELECT ITEM_VALUE FROM kf_attr_value z WHERE z.obj_id=449 and z.attr_id = 197) uchreditel,
(
SELECT ITEM_VALUE FROM kf_attr_value z WHERE z.obj_id=449 and z.attr_id = 168) raion from kf_attr_value


..и тп.
Разница в скорости будет заметна? ЧТо быстрее подзапрос или джоин?
vital 

Но переписывать было лениво ибо время. А вот обвинять меня в незнании чего-то не стоит.
Попутно решил вот завести дисуссию - джоин вс подзапрос.
Емнип, на mysql подзапросы могут давать больший оверхед, чем джоин. Решил спросить про оракл. Вот и все.

Спустя 11 минут, 45 секунд (1.04.2012 - 12:20) sergeiss написал(а):
Цитата (vital @ 1.04.2012 - 13:09)
А вот обвинять меня в незнании чего-то не стоит.

Слющай, дарагой! Ни обижайси, да? smile.gif Я просто удивился, но не обвинял тебя ни в чем. Я знаю, что ты человек адекватный и думающий.

Также обрати внимание на то, что "мой" запрос позволяет выбрать данные для любого диапазона obj_id - а у тебя в "переписанном" запросе только для определенных obj_id. Для этого я я использую очень мощное дополнение к запросу в виде WITH, которого нету у Мускуля. Но оно есть в Оракле и в моём любимом Постгре. Эта штуковина позволяет сначала сделать (в данном случае) выборку уникальных obj_id, а потом уже только для них делать выборку. И это всё, прошу заметить, в пределах одного запроса. Подзапрос делаем в явном виде и гарантируем, что он будет выполнен только один раз.
Ежели тебе приходится работать в Оракле, то "возьми на вооружение" эту возможность.


_____________
"Нужно быть готовым прислушиваться к тем, кто может тебя чему-нибудь научить. Иначе ты никогда не вырастешь."

Откровенно я никому ниразу не нагрубил. А дать подзатыльник зарвавшемуся юнцу, так это и ему на пользу, и мне в удовольствие. © AllesKlar
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.