Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Оптимизация запроса FireBird


Страницы:   1 2

Aristarh ©   (2003-07-24 19:39:00) 

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

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


Johnmen   (2003-07-25 19:44:00) [1]

>Aristarh © (25.07.03 19:14)

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


Aristarh   (2003-07-25 19:14:00) [2]

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

>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)))


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


IgorRu   (2003-07-25 15:08:00) [3]

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

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)))


IgorRu   (2003-07-25 13:48:00) [4]

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


Johnmen   (2003-07-25 13:35:00) [5]

>Aristarh © (25.07.03 13:24)

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


Zacho   (2003-07-25 13:32:00) [6]


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

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


Aristarh   (2003-07-25 13:24:00) [7]

>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:19:00) [8]


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

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


KDS   (2003-07-25 13:18:00) [9]

примечание 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


Aristarh   (2003-07-25 13:16:00) [10]

>Zacho © (25.07.03 12:55)

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

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

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


Johnmen   (2003-07-25 13:16:00) [11]

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


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


> Aristarh © (25.07.03 12:41)

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

Aristarh © (25.07.03 12:47)

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


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

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

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


Aristarh   (2003-07-25 12:41:00) [14]

>Zacho © (25.07.03 12:22)

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

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


Zacho   (2003-07-25 12:22:00) [15]


> Aristarh © (25.07.03 12:17)

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


Aristarh   (2003-07-25 12:17:00) [16]

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:09:00) [17]


> Aristarh © (25.07.03 12:01)

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


Zacho   (2003-07-25 12:07:00) [18]


> Aristarh © (25.07.03 11:52)

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


Aristarh   (2003-07-25 12:01:00) [19]

>Sergey13 © (25.07.03 11:56)

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


Sergey13   (2003-07-25 11:56:00) [20]

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


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо