Привет народ.
Сто лет молчал хочется сказать. Накипело.
Прошу не голословно писать, а только по поводу. ЛУЧШЕ (ДА, НЕТ или может
так)
Если нечего сказать по сути лучше промолчать.
И ТОЛЬКО ПО ПРОЧТЕНИИ ВСЕГО В ЦЕЛОМ.
Думаю у кого мелкие запросы моя мысль не заинтересует. А вот у кого огромные
процедуры с множеством условий, которые хотелось хоть как то ускорить
заинтересуются. Хотя я уже разочарован давно в этом мире и пишу для себя
всякие хитрушки упрощающие жизнь.
То что здесь приводится это упрощенный вариант для наглядности на самом деле
условие в WHERE намного больше и сложней.
К примеру (0-все организации, 1 только выбранные, 2 кроме выбранных)
((:AD500_6 = 0) or
(:AD500_6 = 1 and EXISTS(SELECT * FROM D503 WHERE D503.D500_1 =
:AD500_1 and D503.D009_1 = T003.D009_1b)) or
(:AD500_6 = 2 and not EXISTS(SELECT * FROM D503 WHERE D503.D500_1 =
:AD500_1 and D503.D009_1 = T003.D009_1b)) )
Сначала начал пользоваться EXECUTE STATEMENT в 2 - 3 местах. Но потом
воткнул еще в несколько. А уж когда появилась возможность
EXECUTE STATEMENT (...) (и тут параметры)
я быстренько переписал запросы.
Но вся радость закончилась когда я написал, что то подобное этому:
EXECUTE STATEMENT
('SELECT cast(:X as int) FROM RDB$DATABASE')
(x := :x, y := :y)
не заметившим или не знающим объясняю параметр :y не участвует в запросе и
получаем крик от сервера.
Поняв, что затея заменить часть запросов не удалась из за громоздкости
реализации я остановился на том что уже использую.
И вот наткнулся на довольно простенький зарос который оказалось только в
периоде 1-го дня почему то делает более 36000 чтений из таблицы документы. У
очень маленькой организации (База за несколько лет всего 270 Мб, работают с
документами). Я давай рыть и отписался ДЯ и он вот это разъяснил
(:NextID = T003_1) or
(:NextID IS NULL and
(:I_IDDOC = T003.IDDoc or :I_IDDOC IS NULL) and
T003_3 = :I_FD and T003_3 = :I_TD and
(D009_1 = :I_D009_1 or D009_1b = :I_D009_1) )
занчение в NextID 100% есть получаем 12000 чтений
как всегда быстро сказал, что к чему. Оказывается сервер все, что после
(:NextID = T003_1) or не совсем понимает, что это условие всегда FALSE и
лопатит по записям хотя я считал что скобки с :NextID IS NULL дадут ему
понять что условие не выполнимо.
Это получается тоже как бы не фонтан по сути.
((:AD500_6 = 0) or
(:AD500_6 = 1 and EXISTS(...)) or
(:AD500_6 = 2 and not EXISTS(...)) )
Настроение упало ниже плинтуса ибо все запросы в отчетах так и построены в
которых
(или или или) и (или или или) и (или или или) и (или или или) и (или или
или) и (или или или)
Мне разработчики говорят мол идиотские запросы у тебя.
А теперь объясните как описать такое:
Немного вникнем в тему клиент говорит я хочу реестр
товар, кол-во, сум
я кричу, а это просто и тут поражаюсь количеству вариаций. При условии
выбора
1.Нужно выбрать нашу или несколько наших организаций по которым дать
результат тут просто join
2.Теперь хочу указать склады (все или по всем или кроме выбранных)
3.Теперь хочу указать кладовщики (все или по всем или кроме выбранных)
4.Теперь хочу указать клиенты (все или по всем или кроме выбранных)
5.Теперь хочу указать типы документов (все или по всем или кроме выбранных)
6.Теперь хочу указать товары (все или по всем или кроме выбранных)
как здесь сделать UNION или JOIN дабы никого не обидеть с условием
(или или или) и (или или или) и (или или или) и (или или или) и (или или
или) и (или или или)
ТАК ВОТ после того как Vlad Khorsun мне сказал это не кому не интересно иди
в конфу я пришел сюда узнать надо оно или нет.
Что бы ускорить запрос я его переписал и получил на 17640 чтений меньше
вместо 36680 всего 19040
БЫЛО
SELECT COUNT(*) FROM T003 WHERE
(:I_ID IS NOT NULL and (:I_ID = T003_1 or :I_ID = T003_1b)) or
(:I_ID IS NULL and
(:I_IDDOC = T003.IDDoc or :I_IDDOC IS NULL) and
T003_3 = :I_FD and T003_3 = :I_TD and
(D009_1 = :I_D009_1 or D009_1b = :I_D009_1) )
for update
INTO :F_COUNT;
СТАЛО
тут не КРИЧАТЬ ибо после этого делается тоже тело но с FOR EXECUTE STATEMENT
первый надо было для оценки времени выполнения. В теле FOR EXECUTE STATEMENT
масса вызовов процедур. Я понимаю, что можно начать разбивать на массу
процедурок тело, потом кучу раз написать циклы вызывать это дробленое
безобразие. Потом не один пионер не разберется, что я написал. Ладно
смотрим, что же получилось:
sSQL = '';
if (I_ID IS NOT NULL) then begin
sSQL = sSQL || ' (:I_ID = T003_1 or :I_ID = T003_1b) ' ||
' and :I_IDDOC IS NULL' ||
' and cast(:I_FD as DATE) is not distinct from cast(:I_FD as DATE)' ||
' and cast(:I_TD as DATE) is not distinct from cast(:I_TD as DATE)' ||
' and cast(:I_D009_1 as varchar(38)) is not distinct from
cast(:I_D009_1 as varchar(38))';
end else begin
sSQL = sSQL || ' :I_ID is null';
if (I_IDDOC IS NOT NULL)
then sSQL = sSQL || ' and :I_IDDOC = T003.IDDoc';
else sSQL = sSQL || ' and :I_IDDOC is null';
sSQL = sSQL