Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Как ускорить запрос с between'ом / 11 сообщений из 11, страница 1 из 1
09.06.2004, 07:04:20
    #32553374
MVal
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ускорить запрос с between'ом
Добрый день.
Есть у меня две процедуры, возвращающие наборы данных.

ALTER PROCEDURE GETUPL (
ME INTEGER)
RETURNS (
PR INTEGER,
S NUMERIC(15,2))
AS
begin
for
select pr, sum(s) as s from upl where me=:me group by pr
union
select pr, CAST (0 AS numeric(15,2)) as s from sppr where pr not in (select pr from upl where me=:me)
into :pr, :s
do
suspend;
end
и

ALTER PROCEDURE GETUPLBYINT (
ME1 INTEGER,
ME2 INTEGER)
RETURNS (
PR INTEGER,
S NUMERIC(15,2))
AS
begin
for
select pr, sum(s) as s from upl where me between :me1 and :me2
group by pr
union
select pr, CAST (0 AS numeric(15,2)) as s from sppr where pr not in (select pr from upl where me between :me1 and :me2)
into :pr, :s
do
suspend;
end

Где - sppr - таблица-список всех аббанентов. Ключевое поле - pr.
Upl - оплата, произведенная абанентом pr в месяце me.
Первая процедура возвращает оплату за определенный месяц (параметр me), для тех, у кого ее нет возвращает нули. Вторая - то же самое, только за период с me1 до me2.
Первая процедура работает бовольно быстро, а вторая во много раз медленнее (причем не зависимо от расстояния между me1 и me2).
Имею индексы по Sppr.pr, upl.pr, upl.me, upl.(pr,me).
Как можно ускорить этот процес?
...
Рейтинг: 0 / 0
09.06.2004, 08:34:52
    #32553455
Voha
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ускорить запрос с between'ом
http://ibase.ru/devinfo/dontdoit.htm пункт 15. IN-это и есть тормаза процедуры
попробуй поменять чтобы это избежать
...
Рейтинг: 0 / 0
09.06.2004, 11:11:32
    #32553727
Dremuchij Forester
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ускорить запрос с between'ом
Попробуй так:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
CREATE PROCEDURE GETUPL (
    ME INTEGER)
RETURNS (
    PR INTEGER,
    S NUMERIC( 15 , 2 ))
AS
begin
 for SELECT pr FROM upl
  INTO :PR
 do
 begin
  S =  0 ;
  SELECT SUM(s) as s FROM UPL
   WHERE me = :me
    AND  pr = :pr
   GROUP BY pr
   INTO :S;
  suspend;
 end;
end

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
CREATE PROCEDURE GETUPLBYINT (
    ME1 INTEGER,
    ME2 INTEGER)
RETURNS (
    PR INTEGER,
    S NUMERIC( 15 , 2 ))
AS
begin
 for SELECT pr FROM upl
  INTO :PR
do
 begin
  S =  0 ;
  SELECT SUM(s) as s FROM UPL
   WHERE me BETWEEN :ME1 AND :ME2
    AND  pr = :PR
   GROUP BY pr
   INTO :S;
  suspend;
 end;
end

Производительность не оценивал, но IN(SELECT...) это точно тормоз.
...
Рейтинг: 0 / 0
09.06.2004, 11:41:10
    #32553814
doroshka
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ускорить запрос с between'ом
С IN - все понятно. Основный тормоза от него, но вот, кстати, интересно UNION как-то влтяет на производительность. Я бы, например, в таком случае:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
.....
for
select pr, sum(s) as s from upl where me=:me group by pr
union
select pr, CAST ( 0  AS numeric( 15 , 2 )) as s from sppr where pr not in (select pr from upl where me=:me)
into :pr, :s
do
suspend;
....

Написал бы так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
....
for select pr, sum(s) as s from upl where me=:me group by pr
     into :pr, :s
do  
  suspend;

s= 0 ;
for select pr from sppr where pr not in (select pr from upl where me=:me)
     into :pr
do
   suspend;
....
Есть ли какая-то разница по скорости? Или это те же яйца только с боку?
...
Рейтинг: 0 / 0
14.06.2004, 06:22:21
    #32559992
MVal
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ускорить запрос с between'ом
Спасибо всем, кто откликнулся.
Как не странно (хотя, наверное ничего странного в этом нет) производительность данного (и других ему подобных) запросов многократно возрасла заменой IB 6.0.1 на FB 1.5. Видимо он более корректно работает с индексами.

2 Dremuchij Forester Спасибо за вариант, только я толком не понял, что он там возвращает (видимо не то, что я хотел). А хоте я так просуммировать все S с группировкой по PR из UPL и дополнить ее теми номерами ( PR ), которых нет в UPL .

2 doroshka Спасибо. Без union'а действительно полегче. Так "оригинальный" запром выполняется в среднем за 70 мс, а твой - за 10.
...
Рейтинг: 0 / 0
14.06.2004, 13:25:02
    #32560270
dimitr
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ускорить запрос с between'ом
MValСпасибо. Без union'а действительно полегче. Так "оригинальный" запром выполняется в среднем за 70 мс, а твой - за 10.

Я бы на твоем месте изначально заменил UNION на UNION ALL и получил бы те же самые 10 мс.
...
Рейтинг: 0 / 0
15.06.2004, 10:18:55
    #32561054
doroshka
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ускорить запрос с between'ом
dimitr...заменил UNION на UNION ALL и получил бы те же самые 10 мс.
Спасибо, это и интересно было узнать.
...
Рейтинг: 0 / 0
15.06.2004, 10:55:57
    #32561124
Dremuchij Forester
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ускорить запрос с between'ом
Ага, накосячил. Надо в обеих процедурах
...
for SELECT pr FROM /* не upl , а*/ sppr
INTO :PR
do
...
...
Рейтинг: 0 / 0
21.06.2004, 09:13:46
    #32568944
MVal
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ускорить запрос с between'ом
2remuchij Forester
А вот теперь заработал как надо.
Что касается скорости выполнения то вариант doroshka (то же с union all) на FB 1.5 работает в полтара раза быстрее. Зато на IB 6 или на FB 1.0 твой вариант значительно быстрее (примерно раз в 100).
...
Рейтинг: 0 / 0
22.06.2004, 19:36:36
    #32572637
Ярослав Татаренко
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ускорить запрос с between'ом
NOT IN замечательно меняется на NOT EXISTS, при этом значительно возрастает скорость, а еще лучше в данном случае на JOIN. UNION меняем на UNION ALL, правда нужно посмотреть на повторяемость результирующих записей.
...
Рейтинг: 0 / 0
23.06.2004, 06:53:50
    #32572870
MVal
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как ускорить запрос с between'ом
Вообщем то да. Вариант с not exist получше (почти в полтора раза быстрее).
Про union я уже давно понял, что был не прав.
Вообщем нет предела совершенству :-)
...
Рейтинг: 0 / 0
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Как ускорить запрос с between'ом / 11 сообщений из 11, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]