Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.08.21;
Скачать: CL | DM;

Вниз

Оптимизация запроса FireBird   Найти похожие ветки 

 
Aristarh ©   (2003-07-24 19:39) [0]

Неужели все сортировки настолько(!) тормозят запрос?
Запросы:

SELECT SA.SALDODATE, S.NAME, A.HOUSE, A.LITERA, A.FLAT, A.FIO, SALDOIN, NACH, PAY, SALDOOUT, SA.ID
FROM STREETS S,
ABONENTS A,
SALDO SA
WHERE
(
(SA.SALDODATE = "01.07.2003")
and
(SA.ID = A.ID)
and
(S.CODE = A.STREET)
)
order by Streets.Name, House, Litera, Flat


Либо:

SELECT SA.SALDODATE, S.NAME, A.HOUSE, A.LITERA, A.FLAT, A.FIO, SALDOIN, NACH, PAY, SALDOOUT, SA.ID
FROM SALDO SA
INNER JOIN ABONENTS A ON (SA.ID = A.ID)
INNER JOIN STREETS S ON (A.STREET = S.CODE)
WHERE
(
(SA.SALDODATE = "01.07.2003")
)
order by Streets.Name, House, Litera, Flat


Выполняются 5 секунд каждый. Это запросы, которые возвращают одну и ту же выборку.

Стоит только убрать сортировку, т.е. строку
order by Streets.Name, House, Litera, Flat
как запросы начинают выполняться за 50 милисекунд (!!) В сто раз быстрее. Причем неважно какая сортировка, т.е. даже при сортировке по простому индексированому Saldo.ID все равно наблюдается замедление в 100 раз. (5 сек)

Как можно уменьшить время сортировки? Или все безнадежно?

Структура таблиц:

SALDO:
ID INTEGER NOT NULL, (индекс)
SALDOIN DOUBLE PRECISION,
NACH DOUBLE PRECISION,
PAY DOUBLE PRECISION,
SALDOOUT DOUBLE PRECISION,
SALDODATE DATE NOT NULL (индекс)

ABONENTS:
ID INTEGER NOT NULL, (primary key)
FIO CHAR(30) NOT NULL, (индекс)
STREET INTEGER, (индекс)
HOUSE SMALLINT,
LITERA CHAR(3),
FLAT SMALLINT,

STREET:
CODE INTEGER NOT NULL, (primary key)
( 50) Неужели все сортировки настолько(!) тормозят запрос?
Запросы:

SELECT SA.SALDODATE, S.NAME, A.HOUSE, A.LITERA, A.FLAT, A.FIO, SALDOIN, NACH, PAY, SALDOOUT, SA.ID
FROM STREETS S,
ABONENTS A,
SALDO SA
WHERE
(
(SA.SALDODATE = "01.07.2003")
and
(SA.ID = A.ID)
and
(S.CODE = A.STREET)
)
order by Streets.Name, House, Litera, Flat


Либо:

SELECT SA.SALDODATE, S.NAME, A.HOUSE, A.LITERA, A.FLAT, A.FIO, SALDOIN, NACH, PAY, SALDOOUT, SA.ID
FROM SALDO SA
INNER JOIN ABONENTS A ON (SA.ID = A.ID)
INNER JOIN STREETS S ON (A.STREET = S.CODE)
WHERE
(
(SA.SALDODATE = "01.07.2003")
)
order by Streets.Name, House, Litera, Flat


Выполняются 5 секунд каждый. Это запросы, которые возвращают одну и ту же выборку.

Стоит только убрать сортировку, т.е. строку
order by Streets.Name, House, Litera, Flat
как запросы начинают выполняться за 50 милисекунд (!!) В сто раз быстрее. Причем неважно какая сортировка, т.е. даже при сортировке по простому индексированому Saldo.ID все равно наблюдается замедление в 100 раз. (5 сек)

Как можно уменьшить время сортировки? Или все безнадежно?

Структура таблиц:

SALDO:
ID INTEGER NOT NULL, (индекс)
SALDOIN DOUBLE PRECISION,
NACH DOUBLE PRECISION,
PAY DOUBLE PRECISION,
SALDOOUT DOUBLE PRECISION,
SALDODATE DATE NOT NULL (индекс)

ABONENTS:
ID INTEGER NOT NULL, (primary key)
FIO CHAR(30) NOT NULL, (индекс)
STREET INTEGER, (индекс)
HOUSE SMALLINT,
LITERA CHAR(3),
FLAT SMALLINT,

STREET:
CODE INTEGER NOT NULL, (primary key)
NAME VARCHAR(50) NOT NULL


 
Sergey13 ©   (2003-07-25 08:23) [1]

>Неужели все сортировки настолько(!) тормозят запрос?
Не все. Вернее все, но не все "настолько(!)".
А что тебя так удивляет? Сколько записей возвращает запрос? Тем паче что первое сортируемое поле VARCHAR(50).


 
Johnmen ©   (2003-07-25 09:14) [2]

Смотри планы выполнения запросов. Возможно, удастся оптимизировать...


 
Zacho ©   (2003-07-25 09:42) [3]

Какая версия FB ? Подозреваю, что попробовав выполнить тот же запрос на FB 1.5 или Yaffil ты приятно удивишься.


 
Aristarh ©   (2003-07-25 11:52) [4]

>Sergey13 © (25.07.03 08:23)

Запрос возвращает порядка 5 тыс. записей из таблицы Saldo, в
которой содержится всего ~150 тыс. записей.

>Тем паче что первое сортируемое поле VARCHAR(50).

Даже по целому Saldo.ID время выполнения точно такое
же: 5 сек. Так что VARCHAR ни при чем.

>Johnmen © (25.07.03 09:14)

Возможно и удастся... Где можно план посмотреть?

>Zacho © (25.07.03 09:42)

Версия Firebird-1.0.0.796-Win32


 
Sergey13 ©   (2003-07-25 11:56) [5]

А че - нормально. 5000 записей отсортировать по 4 полям - это что просто что ли? Уменьшай количество - выиграешь в скорости. 5000 сразу все равно никому не нужно (как правило).


 
Aristarh ©   (2003-07-25 12:01) [6]

>Sergey13 © (25.07.03 11:56)

А если не по четырем полям? А по Saldo.ID?
Да и нужна такая сортировка, это отчетность в бухгалтерию, вразнобой никак.


 
Zacho ©   (2003-07-25 12:07) [7]


> Aristarh © (25.07.03 11:52)

Если я все правильно путаю :), то использования временных файлов в памяти для сортировки есть только в Yaffil (и может быть в FB 1.5). А в IB - FB 1.0 для этого используются временные файлы на диске, отсюда и тормоза даже при наличии индекса.
А посмотреть план запроса можно в любом инструменте для работы с IB - IBConsole, IBExpert и т.д., да хоть в isql.exe


 
Zacho ©   (2003-07-25 12:09) [8]


> Aristarh © (25.07.03 12:01)

А для отчетов это не существенно, все равно основное время уйдет на фетч такого резалтсета на клиента.


 
Aristarh ©   (2003-07-25 12:17) [9]

Plan:
PLAN SORT (JOIN (A NATURAL,S INDEX (RDB$PRIMARY11),SA INDEX (IXSALDOID,IXSALDODATE)))

Adapted plan:
PLAN SORT (JOIN (A NATURAL,S INDEX (INTEG_72),SA INDEX (IXSALDOID,IXSALDODATE)))

>А для отчетов это не существенно, все равно основное время
>уйдет на фетч такого резалтсета на клиента.

Если убрать сортировку, то резалтсет ведь не изменится, и время его доставки тоже. Происходит мгновенно.


 
Zacho ©   (2003-07-25 12:22) [10]


> Aristarh © (25.07.03 12:17)

FetchAll 5000 записей мнговенно ? Не верю. Разве что на локальном компе с быстрым винтом и достаточным объемом памяти.


 
Aristarh ©   (2003-07-25 12:41) [11]

>Zacho © (25.07.03 12:22)

Нет, IBExpert в SQL builder"e фетчит лишь сколько на экране.
Но все равно, причем здесь такая долгая сортировка?

Кстати, таже база, но по сети. Время увеличилось не на много 60мс. вместо 50мс


 
Aristarh ©   (2003-07-25 12:47) [12]

Ставлю Firebird-1.5.0.3744-RC4-Win32
Что лучше выбрать SuperServer или Classic?

Нагрузка:
-две БД по 25 мегабайт каждая.
-5 клиентских машин, которые обращаются к каждой из баз.


 
Zacho ©   (2003-07-25 12:55) [13]


> Aristarh © (25.07.03 12:41)

Есть время выполнения запроса и время фетча. Похоже, ты просто путаешь одно с другим. А для построения отчета придется фетчить все записи резалтсета на клиента, это и займет основное время, особенно по сети.
А долгая сортировка потому, что резалтсет не влезает в кэш сервера и происходит сортировка во временных файлах на диске. Если я что-то напутал, то пусть более знающие товарищи поправят и уточнят.
Как вариант решения - запрос без сортировки и сортировка уже полученного резалтсета в клиентском приложении, или действительно посмотри как это работает в Yaffil или FB 1.5

Aristarh © (25.07.03 12:47)

Если сервер многопроцессорный - то Classic


 
Johnmen ©   (2003-07-25 13:16) [14]

Разница во времени выполнения запроса без сортировки (или с сортировкой по saldo.id) (1) и с сортировкой по полям не таблицы saldo (2) прекрасно объясняется при просмотре планов выполнения обоих.


 
Aristarh ©   (2003-07-25 13:16) [15]

>Zacho © (25.07.03 12:55)

Поставил FB 1.5
Ну мля.... время выполнения стало 1.3 сек вместо 5.5 сек!

С первой версией полная совместимость? Можно ли безболезненно ставить на сервер версию 1.5?

За счет чего такой прирост?


 
KDS ©   (2003-07-25 13:18) [16]

примечание 1: IB существует в двух архитектурах - Classic (CS) и SuperServer (SS). Архитектура Classic использует отдельные процессы на каждого пользователя, SuperServer - отдельные threads на пользователя в общем процессе. SS обладает общим кэшем, который увеличивает производительность, а CS благодаря разделению пользователей по процессам обладает большей надежностью. UDF для CS выполняются в адресном пространстве пользователя, а для SS - в общем адресном пространстве сервера. Поэтому в UDF для CS можно использовать глобальные константы, а в SS - нельзя. Для Windows IB существует только как SuperServer. Документы по отличиям CS от SS от Borland и IBPhoenix.

(C) http://www.ibase.ru/ib6.htm


 
Zacho ©   (2003-07-25 13:19) [17]


> Aristarh © (25.07.03 13:16)
>
> С первой версией полная совместимость? Можно ли безболезненно
> ставить на сервер версию 1.5?

Можно, только стоит сделать backup базы под FB 1.0 и потом restore под FB1.5


 
Aristarh ©   (2003-07-25 13:24) [18]

>Zacho © (25.07.03 13:19)

А что используется другая дисковая структура?

>KDS © (25.07.03 13:18)

CS уже есть и под виндовс.

>Johnmen © (25.07.03 13:16)
PLAN SORT (JOIN (A NATURAL,S INDEX (INTEG_72),SA INDEX (IXSALDOID)))

PLAN JOIN (A NATURAL,S INDEX (INTEG_72),SA INDEX (IXSALDOID))

разница только в SORT


 
Zacho ©   (2003-07-25 13:32) [19]


> Aristarh © (25.07.03 13:24)
> >Zacho © (25.07.03 13:19)
>
> А что используется другая дисковая структура?

Вроде бы ODS та же, но на всякий случай...


 
Johnmen ©   (2003-07-25 13:35) [20]

>Aristarh © (25.07.03 13:24)

Ну да. Так ведь сортировка в данном случае производится над выходным потоком, без использования индексов. А это не очень быстро...:)
Отсортируй только по saldo.id и посмотри план. Это поможет в понимании.
И ещё см. http://www.krista.ru/ib/ - весьма полезно.


 
IgorRu ©   (2003-07-25 13:48) [21]

Специально создал структуру похожую на описанную выше. Заполнил небольшим количеством данных и проверил отработку Планов.
Если пользовать запрос where and то в Плане появляется JOIN (A NATURAL это приводит к тому, что на каждую выбранную запись приходится перебирать всю таблицу ABONENTS. В случае использования в запросе соединения JOIN в Плане все проходит по индексам.
Резюме
Ускорить выборку до безобразия при использовании сортировки не удастся, но оптимизировать и сделать так, чтобы с ростом количества записей в таблице ABONENTS время запроса заметно не увеличивалось можно, используя соединения JOIN


 
IgorRu ©   (2003-07-25 15:08) [22]

Даже при сортировке то по Streets.Name или Streets.ID PLAN выглядит так:

PLAN SORT (JOIN (S NATURAL,A INDEX (ABONENTS_IDX2),SA INDEX (PK_SALDO)))

а при использовании соединения JOIN так:

PLAN SORT (JOIN (SA INDEX (SALDO_IDX1),A INDEX (PK_ABONENTS),S INDEX (PK_STREET)))


 
Aristarh ©   (2003-07-25 19:14) [23]

Спасибо всем. Разбирусь с планами, ветку возможно подниму.

>IgorRu © (25.07.03 15:08)

Нет, при запросе с JOIN

SELECT SA.SALDODATE, S.NAME, A.HOUSE, A.LITERA, A.FLAT, A.FIO, SALDOIN, NACH, PAY, SALDOOUT, SA.ID
FROM SALDO SA
INNER JOIN ABONENTS A ON (SA.ID = A.ID)
INNER JOIN STREETS S ON (A.STREET = S.CODE)
WHERE
(
(SA.SALDODATE = "01.07.2003")
( JOIN (A NATURAL,S INDEX (RDB$PRIMARY11)
Спасибо всем. Разбирусь с планами, ветку возможно подниму.

>IgorRu © (25.07.03 15:08)

Нет, при запросе с JOIN

SELECT SA.SALDODATE, S.NAME, A.HOUSE, A.LITERA, A.FLAT, A.FIO, SALDOIN, NACH, PAY, SALDOOUT, SA.ID
FROM SALDO SA
INNER JOIN ABONENTS A ON (SA.ID = A.ID)
INNER JOIN STREETS S ON (A.STREET = S.CODE)
WHERE
(
(SA.SALDODATE = "01.07.2003")
)
order by Streets.Name, House, Litera, Flat



план выглядит так:
Plan:
PLAN SORT (JOIN (A NATURAL,S INDEX (RDB$PRIMARY11),SA INDEX (IXSALDOID)))

Adapted plan:
PLAN SORT (JOIN (A NATURAL,S INDEX (INTEG_72),SA INDEX (IXSALDOID)))


Т.е. теже самые натуралы :))


 
Johnmen ©   (2003-07-25 19:44) [24]

>Aristarh © (25.07.03 19:14)

Так попробуй же этот запрос с ORDER BY SA.id !!! Посмотри план !



Страницы: 1 вся ветка

Текущий архив: 2003.08.21;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.019 c
3-68174
Tahion2
2003-07-29 15:26
2003.08.21
Как сохранить в файл информацию про отображение таблицы?


1-68319
IGoRka
2003-08-08 17:58
2003.08.21
как узнать завершение роботи программи ...


6-68431
FireMan_Alexey
2003-06-05 15:38
2003.08.21
TSocketServer! Возможно ли сделать именно так?


7-68566
hsi
2003-06-06 10:58
2003.08.21
Как получить количество страниц посылаемых на печать???


14-68548
Виталий Чернышенко
2003-08-04 23:40
2003.08.21
Юрий Зотов попал в серьезное ДТП