Страница 1 из 1

union глюк или я что-то не так делаю

Добавлено: 16 янв 2006, 14:13
Gall
fierbird 1.5.2 под линуха
создаю сиквел с использованием union из двух частей
если поотдельности эти части запускать, тo IBExpert показывает Execute time равный милисекундам, если же обьединяю то результат уже 3 секунды. при этом тот же самый IBExpert в Performance analysis показывает ображение к одной таблице около 500000 раз, хотя в таблицах не более 500 записей.

весь этот тормоз возникает из-за того что я считаю суммы внутри запросов

(
...select sum( ssm.zena*ssm.kolvo*(select vk_.kyrs from valuta_kyrs vk_ where
vk_.date_ =(select max(vk1_.date_) from val.....
)

если заместо union использую union all и убираю order by то запрос выполнется моментально.

что делать? может в настройках сервера что-то надо менять? или вообще нельзя делать юнионы запросам с такой структурой?

Добавлено: 16 янв 2006, 15:27
Dimitry Sibiryakov
Да, подзапрос действительно тяжелый. Я бы на твоем месте загнал всю эту бодягу SP и развернул сложный подзапрос в пару простых.

Добавлено: 16 янв 2006, 15:59
Gall
Dimitry Sibiryakov писал(а):Да, подзапрос действительно тяжелый. Я бы на твоем месте загнал всю эту бодягу SP и развернул сложный подзапрос в пару простых.
а как я это сделаю в ХП? для каждого елемента надо считать его цену в выбраной валюте, потом всё равно юнион делать.

Добавлено: 16 янв 2006, 16:13
kdv
уж сколько раз советовали - храните ТЕКУЩИЕ (последние) значения курса валюты, чтобы не шарить по всей таблице валют запросами select max(course_date)...

Re: union глюк или я что-то не так делаю

Добавлено: 16 янв 2006, 18:11
hvlad
Gall писал(а):fierbird 1.5.2 под линуха
создаю сиквел с использованием union из двух частей
если поотдельности эти части запускать, тo IBExpert показывает Execute time равный милисекундам, если же обьединяю то результат уже 3 секунды.
fetch в первом случае, fetch all (внутри сервера, дабы удалить дубликаты) во втором
Gall писал(а):если заместо union использую union all и убираю order by то запрос выполнется моментально.
Т.к. сервер перестаёт выполнять весь запрос
Gall писал(а):что делать? может в настройках сервера что-то надо менять? или вообще нельзя делать юнионы запросам с такой структурой?
Запросы писать нормальные (а не "сиквелы") к нормально спроектированным стр-рам данных

Добавлено: 17 янв 2006, 13:32
Gall
kdv писал(а):уж сколько раз советовали - храните ТЕКУЩИЕ (последние) значения курса валюты, чтобы не шарить по всей таблице валют запросами select max(course_date)...
дело в том, что я ищу не последнюю дату, а дату сответствующую дню закупки либо продажи. если есть какой-то метод для ускорения такого поиска, то подскажите.

Добавлено: 17 янв 2006, 13:47
Merlin
Сделай descending index по дате в журнале курсов.

Добавлено: 17 янв 2006, 13:52
kdv
а дату сответствующую дню закупки либо продажи
опять же, тогда надо организовать систему (таблицу курсов валют) так, чтобы курс существовал на каждый день. И при выборке просто искать соответствие дате закупки или продажи, а не по max.

Добавлено: 17 янв 2006, 14:52
Gall
Merlin писал(а):Сделай descending index по дате в журнале курсов.
время выборки уменьшилось в два раза, большое спасибо


kvd, строить систему чтобы курс существовал на каждый день не очень удобно, но видимо необходимо.
тогда встречный вопрос - поддерживает ли firebird какие-либо аналоги jobs из MSSQLServer? Я поискал, но не нашел.

Добавлено: 17 янв 2006, 15:08
Merlin
kdv писал(а):
а дату сответствующую дню закупки либо продажи
опять же, тогда надо организовать систему (таблицу курсов валют) так, чтобы курс существовал на каждый день. И при выборке просто искать соответствие дате закупки или продажи, а не по max.
Не всегда прокатывает. Вспомни дефолт - пять раз на дню курс менялся. Самое простое - денормализация. То есть, при выполнении соответсвующего действия с документом (зависит от политики фирмы, начало оформления или утверждение) брать курс из журнала и укладывать в заголовок документа.

Добавлено: 17 янв 2006, 15:24
Merlin
2 Gall

Спробуй ещё такую конструкцию

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

Select Sum(Doc.Cena*Doc.Kolvo*R1.Rate)
From Doc Join Rates R1 On R1.Valuta=Doc.Valuta
  And R1.Data=(Select Max(R2.Data)
                       From Rates R2 
                       Where R2.Valuta=Doc.Valuta
                           And R2.Data<=Doc.Data)
В принципе почти то же самое, но может оказаться шустрее.