Форум: "Базы";
Текущий архив: 2002.07.22;
Скачать: [xml.tar.bz2];
ВнизВремя выполнения запроса Найти похожие ветки
← →
KAA (2002-06-28 18:00) [0]Есть запрос, выполняется примерно секунду, может иногда две. Но если в WHERE сдлеать хотя бы проверку переменой на NOT NULL, запрос выполняется уже 10секунд. А если там будет проверка типа
((@UIDService=journal_service.UIDService) or (@UIDService IS NULL))
он уже выполняется 20 секуд, независимо от количества таких проверок.
Если добавить просто проверку какого либо поля базы, на время запроса не сказывается. Т.е. чем-то ему не нравятся переменные в области WHERE.
В чем может быть проблема?
← →
KAA (2002-06-28 18:00) [1]Да, речь идет о MSSQL 2000
← →
Shaman_Naydak (2002-06-28 18:55) [2]А какой смысл заранее посчитанное значение в запросе проверять на NULL ?
← →
dimis (2002-06-28 18:56) [3]какой sql не важно
скорее всего запрос составнен не совсем грамотно
напиши его полностью
← →
TSV (2002-06-28 19:09) [4]Есть такая буква в этом слове...
Допустим, вы пишите процедуру для многокритериального поиска. Причем некоторые (любые) параметры могут быть опущены при вызове (в процедуру они прийдут как NULL). Тогда в теле запроса нужно писать:
...
where (...)
and (@Param1 is NULL or Field1 = @Param1)
...
В случае символьных параметров этого можно избежать, указав перед запросом:set @Param1 = COALESCE(@Param1, "%")
Почему происходят тормоза, я не знаю. Скорее всего, это вопрос к разработчикам из MS. Что-то не так с оптимизатором...
А нам, простым смертным, остается по возможности избегать таких выражений в запросах, подставлять значения по умолчанию и т.д.
С уважением.
← →
TSV (2002-06-28 19:17) [5]Кстати, в семерке то же самое...
И еще: когда писал про опущенные параметры, имел в виду вот что:
CREATE PROCEDURE dbo.FindXXX
@Param1 int = NULL
,@Param2 datetime = NULL
,@Param3 varchar(30) = NULL
AS BEGIN
...
...
END
← →
KAA (2002-06-28 19:40) [6]>А какой смысл заранее посчитанное значение в запросе проверять на NULL ?
Я передаю параметры с хранимую процедуру, которые учавствуют в запросе.
>Почему происходят тормоза, я не знаю. Скорее всего, это вопрос к разработчикам из MS
Учитывая, что с MSSQL я работаю меньше года, подозреваю что это мой глюк.
>напиши его полностью
Выполняю
CREATE PROCEDURE JournalServiceSelect
@UIDService int = NULL,
@UIDBill int = NULL,
@UIDPayer int = NULL,
@UIDRecipient int = NULL,
@Pay int = NULL,
@Charge int = NULL,
@DTPayBegin datetime = NULL,
@DTPayEnd datetime = NULL,
@DTChargeBegin datetime = NULL,
@DTChargeEnd datetime = NULL,
@UIDManPay int = NULL,
@UIDManCharge int = NULL,
@UIDManClient int = NULL,
@Ordering int = NULL
AS
IF ((@Ordering IS NULL) or (@Ordering>0)) SET @Ordering=0
IF (@UIDService=0) SET @UIDService=NULL
IF (@UIDBill=0) SET @UIDBill=NULL
IF (@UIDPayer=0) SET @UIDPayer=NULL
IF (@UIDRecipient=0) SET @UIDRecipient=NULL
IF (@UIDManPay=0) SET @UIDManPay=NULL
IF (@UIDManCharge=0) SET @UIDManCharge=NULL
IF (@UIDManClient=0) SET @UIDManClient=NULL
IF (@Pay IS NULL) SET @Pay=0
IF (@Charge IS NULL) SET @Charge=0
IF @Ordering<=0 BEGIN
SELECT TOP 1000
journal_service.UID,
journal_service.UIDOwner,
journal_service.DTInsert,
journal_service.DTUpdate,
journal_service.UIDService,
journal_service.UIDBill,
list_service.Caption AS CaptionService,
list_unit.Caption AS CaptionUnit,
journal_service.Quantity,
journal_service.Lag,
journal_service.Discount,
journal_service.Taxrate,
journal_service.Caption,
journal_amount.UIDPayer AS UIDRecipient,
journal_amount.UIDRecipient AS UIDPayer,
journal_service.UIDManPay,
journal_service.UIDManCharge,
journal_service.UIDManClient,
journal_service.DTPay,
journal_service.DTCharge,
sum(journal_amount.Amount) AS SumCharge,
CASE WHEN (journal_service.DTPay IS NOT NULL) THEN sum(journal_amount.Amount)
ELSE NULL
END AS SumPay,
CASE WHEN (journal_service.DTPay IS NULL) THEN 1
ELSE 2
END AS Pay,
CASE WHEN (journal_service.DTCharge IS NULL) THEN 1
ELSE 2
END AS Charge
FROM
journal_service
LEFT OUTER JOIN list_service ON journal_service.UIDService = list_service.UID
LEFT OUTER JOIN list_unit ON list_service.UIDUnit = list_unit.UID
LEFT OUTER JOIN (SELECT DISTINCT UIDService, max(DTActual) AS MaxDate
FROM journal_service_taxrate
GROUP BY UIDService) AS max_date ON list_service.UID=max_date.UIDService
LEFT OUTER JOIN journal_service_taxrate ON ((max_date.UIDService=journal_service_taxrate.UIDService) and (max_date.MaxDate=journal_service_taxrate.DTActual))
LEFT OUTER JOIN bind_amount_service ON journal_service.UID=bind_amount_service.UIDJournalService
LEFT OUTER JOIN journal_amount ON bind_amount_service.UIDAmount=bind_amount_service.UID
WHERE
((journal_service.UIDPayer=journal_amount.UIDRecipient) or (bind_amount_service.UIDJournalService IS NULL)) and
((@UIDService=journal_service.UIDService) or (@UIDService IS NULL)) and
((@UIDBill=journal_service.UIDBill) or (@UIDBill IS NULL)) and
((@UIDManPay=journal_service.UIDManPay) or (@UIDManPay IS NULL)) and
((@UIDManCharge=journal_service.UIDManCharge) or (@UIDManCharge IS NULL)) and
((@UIDManClient=journal_service.UIDManClient) or (@UIDManClient IS NULL)) and
(((journal_service.DTPay IS NOT NULL) and (@Pay=2)) or
((journal_service.DTPay IS NULL) and (@Pay=1)) or
(@Pay=0)) and
(((journal_service.DTCharge IS NOT NULL) and (@Charge=2)) or
((journal_service.DTCharge IS NULL) and (@Charge=1)) or
(@Charge=0)) and
((@UIDPayer=journal_service.UIDPayer) or (@UIDPayer IS NULL)) --and
GROUP BY
journal_service.UID,
journal_service.UIDOwner,
journal_service.DTInsert,
journal_service.DTUpdate,
journal_service.UIDService,
journal_service.UIDBill,
list_service.Caption,
list_unit.Caption,
journal_service.Quantity,
journal_service.Lag,
journal_service.Discount,
journal_service.Taxrate,
journal_service.Caption,
journal_amount.UIDPayer,
journal_amount.UIDRecipient,
journal_service.UIDManPay,
journal_service.UIDManCharge,
journal_service.UIDManClient,
journal_service.DTPay,
journal_service.DTCharge
ORDER BY
journal_service.UID
END
GO
← →
Shaman_Naydak (2002-06-28 20:10) [7]Вот что я могу посоветовать реально работающее:
Динамически строй свой запрос:
то есть заведи переменную типа varchar(4000) и в нее потихоньку суммируй по алгоритму:
IF @UIDPayer IS NOT NULL
SET @Str = @STR + and (@UIDPayer=journal_service.UIDPayer)
Это эквивалентно твоей конструкции
((@UIDPayer=journal_service.UIDPayer) or (@UIDPayer IS NULL))
А потом запустишь, как Exec(@Str)...
← →
Shaman_Naydak (2002-06-28 20:11) [8]Блин, кавычки забыл в
NULL
SET @Str = @STR + "and (@UIDPayer=journal_service.UIDPayer)"
← →
kaif (2002-06-29 01:07) [9]LEFT OUTER JOIN - не лучшая задача для оптимизаторов запросов.
← →
Polevi (2002-06-29 10:47) [10]2KAA ©
Присоединяюсь к Shaman_Naydak ©
Только вместо Exec используй sp_executesql
В свое время я здорово ускорил свои отчеты таким способом
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2002.07.22;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.006 c