Главная Новые темы Список тем Задать вопрос Поиск  

Форум "DataBase и SQL"


Язык запросов баз даных


 #0 Deep © 24.04.07 19:48:55 - 26.04.07 11:56:35

ОЧЕНЬ долгое выполнение запроса в Firebird



есть выборки

1)

select STORE_DOC_ID
from RP_CONTRACTOR_METAL('01.01.2007', '01.01.2008')


RP_CONTRACTOR_METAL - хранимая процедура
выполняется 2 секунды, возвращает 7 значений

2)

select *
from L_STORE_DOC LSD

выполняется 2 секунды, возвращает 3821 значений

все красиво, все довольны... НО!

3)

их симбиоз

select *
from L_STORE_DOC LSD
where LSD.ID in (select STORE_DOC_ID from RP_CONTRACTOR_METAL ('01.01.2007', '01.01.2008'))

виснет, ждал около 5 минут, но результата так и не дождался...

ЧТО ЗДЕСЬ НЕ ТАК ? Цитата

 #1 Mystic © 24.04.07 19:54:54

Нет, все правильно, 3821 * 2 = 7624 секунды = 127 минут ~= 2 часа
 #2 Deep © 24.04.07 19:55:54

если заменить позапрос на его реальные значения -- то все отлично....

т.е. вот такой вариант работает на ура

select *
from L_STORE_DOC LSD
where LSD.ID in (4215, 2173, 4225, 4233, 2990, 10425, 10427)


В чем же проблема? в подзапросе нельзя использовать хранимую процедуру? Но почему тогда сервер не выдает ошибку, а просто тупо виснет?
+1 к репутации автора  #3 Mystic © 24.04.07 19:57:54

А вот


SELECT LSD.*
FROM L_STORE_DOC LSD
  , RP_CONTRACTOR_METAL ('01.01.2007', '01.01.2008') CM
WHERE LSD.ID = CM.STORE_DOC_ID

должно отработать быстрее
 #4 Deep © 24.04.07 19:58:13

> #1   Mystic ©
если бы в подзапросе использовались динамические параметры, то да, а если там статика ('01.01.2007', '01.01.2008') - зачем выполнять подзапрос для каждой строки выборки? Глупый сервер?
 #5 Mystic © 24.04.07 19:59:21

>
> В чем же проблема? в подзапросе нельзя использовать хранимую
> процедуру? Но почему тогда сервер не выдает ошибку, а просто
> тупо виснет?


Почему виснет? Выполняется Я же подсчитал, что этот запрос будет выполняться два часа, ты просто плохо ждал.
+1 к репутации автора  #6 Mystic © 24.04.07 20:01:15

> Глупый сервер?

Да глупый. Откуда он знает, что вернет хранмая процедура? А вдруг там стоит рандом? Или еще какая ерунда? Сервер не анализировал хранимую процедуру на предмет того, всегда ли она будет возвращать один и тот же набор данных или нет, он просто выполнил то, что ты написал.
 #7 Deep © 24.04.07 20:01:40

> #3   Mystic ©
да, ты прав так отработало вобще за 1 сек.
        
 #8 Mystic © 24.04.07 20:04:35

Хм... чудно... Значит хранимая процедура выполняется 2 секунды, но если ее вставить в запрос, то выполнится быстрее? Хотя может быть кэш и прочая ерунда
 #9 Deep © 24.04.07 20:05:01

>  #6   Mystic ©
гм... насчет рандома как-то не подумал, действительно процедуры бывают "разные"    Мало ли кто-как извращается.

Вобщем, респект. Очередной +1 к твоей репутации    
 #10 Deep © 24.04.07 20:08:54

> #8   Mystic ©
ну, я с секундомером не засекал, но такое сложилось впечатление. Собственно, здесь наверное может зависеть еще от свободной оперативки на момент выполнения запроса и т.п.    
 #11 Mystic © 24.04.07 20:09:34

Давно я не оптимизировал SQL... Последний раз в результате оптимизации запроса скорость его выполнения уменьшилась с 20 мин до 0.1 сек.
 #12 Deep © 24.04.07 22:20:00

> #11 Mystic  ©
а не подскажешь, можно ли в моем случае указать через план запросов, что подзапрос должен выполнятся только один раз? Просто раньше не доводилось работать с этой возможностью, вот только собрался почитать о служебной конструкции PLAN...  Если дадите ссылки на хорошие статьи - буду признателен.    
 #13 Mystic © 24.04.07 22:25:45

Я не подскажу, ибо никогда с ним не работал... Вообще я говорил исходя из общих знаний SQL, а не конкретно Firebird. А... нескромный вопрос... Зачем тебе?
 #14 Deep © 24.04.07 23:33:15

За последний год пришлось вплотную поработать с Firebird, а вот до этой возможности руки дошли только сейчас. Собственно сначала все проектировалось, потом вносились изменения и дополнения... а счас вот приходит время оптимизации. Да и довольно интересная фича этот план запросов, чтоб просто обойти ее стороной. В общих чертах представление есть, но толку от него, если не применять это на практике?
 #15 Mystic © 25.04.07 00:26:37

я думаю, что большую часть оптимизации можно сделать просто переписав SQL запрос, типа как этот
 #16 Deep © 25.04.07 04:45:13

> #3 Mystic ©

вот так замечательно работает


select LSD.*
from L_STORE_DOC LSD, RP_CONTRACTOR_METAL('01.01.2007', '01.01.2008') RPCM
where LSD.ID = RPCM.STORE_DOC_ID


а вот так (с left join) тоже траблы начинаются...


select LSD.*
from L_STORE_DOC LSD, RP_CONTRACTOR_METAL('01.01.2007', '01.01.2008') RPCM
left join L_CONTRACTOR_DOC LCD on LCD.ID = LSD.CONTRACTOR_DOC_ID
where LSD.ID = RPCM.STORE_DOC_ID


пишет вот такую интересную мессагу:
The cursor identified in the update or delete statement is not positioned on row. No current reccord for fetch operation.

 
+1 к репутации автора  #17 Mystic © 25.04.07 08:29:37

А если так?

select LSD.*
from L_STORE_DOC LSD left join L_CONTRACTOR_DOC LCD on LCD.ID = LSD.CONTRACTOR_DOC_ID,
  RP_CONTRACTOR_METAL('01.01.2007', '01.01.2008') RPCM
where LSD.ID = RPCM.STORE_DOC_ID
 #18 Deep © 25.04.07 11:47:09

>  #17 Mystic  ©
опа, работает!
Вроде не первый год с SQL работаю, а не знал, что так можно сделать.
Респект.
 #19 Mystic © 25.04.07 19:13:58

Наоборот, вполне логично... В секции FROM разделитель запятая. Т. е. ты делаешь выборку из наборов данных
  1) L_STORE_DOC
  2) RP_CONTRACTOR_METAL('01.01.2007', '01.01.2008') RPCM
left join L_CONTRACTOR_DOC LCD on LCD.ID = LSD.CONTRACTOR_DOC_ID

Собственно говоря, слева в левом объединении стоит RP_CONTRACTOR_METAL, а он не может в этом наборе найти недостающие записи, для которых условие LCD.ID = LSD.CONTRACTOR_DOC_ID не выполняется. Или что-то в этом роде, все-таки лучше быть аккуратным.

P. S. А как ты +1 ставишь?
 #20 Deep © 25.04.07 19:41:29

> #19   Mystic ©
та теперь я уже понял, просто раньше у меня было четкое ложное убеждение, что join~ы должны идти обязательно после списка таблиц в разделе from.  


> P. S. А как ты +1 ставишь?
есть такая админская возможность  
 #21 Mystic © 26.04.07 09:42:05

> #20 Deep © 25.04.07 21:41:29

Тогда напиши на досуге интерпретатор SQL. Или просто задумайся над тем, как интерпретируются вопросы... ИМХО, во многих книгах об этом не пишут, и это есть большой минус. Хоть SQL и декларативный язык, но иногда приходится использовать дао для того, чтобы добиться инмеративности...
 #22 Deep © 26.04.07 11:56:35

> Тогда напиши на досуге интерпретатор SQL.
когда-то этим заморачивался    
Правда писал не с нуля, а брал за основу чужой исходник. С алиасами таблиц и полей много намаялся. В итоге -- не дописал, такими вещами надо заниматься ТОТАЛЬНО(без отрыва на основные проекты), а не ФАКУЛЬТАТИВНО.


> во многих книгах об этом не пишут
в том-то и дело, что подобного синтаксиса я нигде ранее не встречал - ни в книгах, ни в статьях. Наверное, не те книжки попадались.    




  • Написать ответ

    Имя: Регистрация HTML?
    smiles смайлики
    Потом перейти в:    
    паутина



      ©  webest.net, 2002-2007  

    top.mail.ru
    » Бесплатный счетчик посещений
    » Рейтинг сайтов