powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Формирование запроса
25 сообщений из 25, страница 1 из 1
Формирование запроса
    #35948851
Naf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
С клиентского приложения формируется запрос
Код: plaintext
Text:='SELECT ... FROM Table';
который должен выбрать все записи,а если пользователь выбрал на форме значение, только с использованием этого условия, поэтому пишем
Код: plaintext
1.
if ВыбраноУсловие then
  Text:=Text+' WHERE Field=:Параметр';
и передаем параметр

Насколько будет критичным не добавлять динамически а формировать запрос так:
Код: plaintext
Text:='SELECT ... FROM Table WHERE (Field=:Параметр) OR (:ВыбраноУсловие=0)';
и передавать соответственно 2 параметра?
С уважением, Naf
...
Рейтинг: 0 / 0
Формирование запроса
    #35949176
Senya_L
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Naf,

Я бы использовал обычную ХП без всякой динамики, имхо.
...
Рейтинг: 0 / 0
Формирование запроса
    #35949204
Naf
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Senya_LNaf,

Я бы использовал обычную ХП без всякой динамики, имхо.
на каждый запрос писать ХП? потом в ХП все равно передавать 2 параметра: значение отбора и флаг установленности отбора
...
Рейтинг: 0 / 0
Формирование запроса
    #35949477
Senya_L
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Nafна каждый запрос писать ХП?Это вопрос предпочтений/возможностей СУБД. Если используете MSSQL, то состав столбцов в выходном рекордсете может быть переменным, а вот в Firebird такое не прокатит.Nafпотом в ХП все равно передавать 2 параметра: значение отбора и флаг установленности отбораИ в чем тут проблема? Передавайте.

ЗЫ. Разок столкнулся с такой ситуацией. При выводе реестра используется флаг, означающий применять или не применять фильтр. Получал странные тормоза. В итоге просто разбил на два запроса с IF ... ELSE. Это я к тому, что условие OR, похоже, СУБД не всегда "переваривают". :)
...
Рейтинг: 0 / 0
Формирование запроса
    #35952224
Фотография Megabyte
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В различных СУБД можно сделать по-разному универсальность запроса с фильтром/без, например:
(field = :param or :param is null).
...
Рейтинг: 0 / 0
Формирование запроса
    #35952654
АнатоЛой
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MegabyteВ различных СУБД можно сделать по-разному универсальность запроса с фильтром/без, например:
(field = :param or :param is null).
это отнюдь не быстрый вариант в любой СУБД, как только количество фильтров увеличится...
...
Рейтинг: 0 / 0
Формирование запроса
    #35958173
Фотография Megabyte
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АнатоЛойMegabyteВ различных СУБД можно сделать по-разному универсальность запроса с фильтром/без, например:
(field = :param or :param is null).
это отнюдь не быстрый вариант в любой СУБД, как только количество фильтров увеличится...
Тестов, канеш, не проводил, но неужели медленнее динамикСкуля будет? :)
Проверка на Null параметра разве медленнее динамического формирования запроса?
...
Рейтинг: 0 / 0
Формирование запроса
    #35958515
АнатоЛой
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MegabyteАнатоЛойMegabyteВ различных СУБД можно сделать по-разному универсальность запроса с фильтром/без, например:
(field = :param or :param is null).
это отнюдь не быстрый вариант в любой СУБД, как только количество фильтров увеличится...
Тестов, канеш, не проводил, но неужели медленнее динамикСкуля будет? :)
Проверка на Null параметра разве медленнее динамического формирования запроса?
Попробуйте на Вашей любимой СУБД с 5-кой таких условий


(field1 = :param1 or :param1 is null)
and
(field2 = :param2 or :param2 is null)
and
(field3 = :param3 or :param3 is null)
and
(field4 = :param4 or :param4 is null)
and
(field5 = :param5 or :param5 is null)

добавьте индексов на эти поля в любых понравившихся комбинациях

и покажите плна запроса. Потом мысленно или реально добавьте в таблицу сотню лимонов записей - и меееедленно проникайтесь...

При динамическом формировании если задан один параметр, то Вы получите только одно условие типа (field4 = :param4 or :param4 is null) с адекватным планом по нему...
...
Рейтинг: 0 / 0
Формирование запроса
    #35958552
tru55
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тут есть еще другой аспект - повторное использование запроса (на примере Oracle).
Если все параметры сразу присутствуют в запросе, то запрос будет использован повторно, при динамике - каждый раз разбор и построение плана выполнения (hard parse).
Поэтому если время выборки значительно превышает время разбора (т.е. когда записей дофига) - это одно, если нет - это другое...
...
Рейтинг: 0 / 0
Формирование запроса
    #35958571
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АнатоЛой(field1 = :param1 or :param1 is null)
and
(field2 = :param2 or :param2 is null)
and
(field3 = :param3 or :param3 is null)
and
(field4 = :param4 or :param4 is null)
and
(field5 = :param5 or :param5 is null)

добавьте индексов на эти поля в любых понравившихся комбинациях

и покажите плна запроса. Потом мысленно или реально добавьте в таблицу сотню лимонов записей - и меееедленно проникайтесь...

При динамическом формировании если задан один параметр, то Вы получите только одно условие типа (field4 = :param4 or :param4 is null) с адекватным планом по нему...
От оптимизатора СУБД зависит. Есть оптимизаторы, которые проводят несколько ступеней оптимизации запроса, в том числе выкидывая с него не используемые таблицы, условия и т.д. Соответственно и план запросов у них будет простым и эффективным.
...
Рейтинг: 0 / 0
Формирование запроса
    #35959683
АнатоЛой
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ASCRUSАнатоЛой(field1 = :param1 or :param1 is null)
...
(field5 = :param5 or :param5 is null)


От оптимизатора СУБД зависит. Есть оптимизаторы, которые проводят несколько ступеней оптимизации запроса, в том числе выкидывая с него не используемые таблицы, условия и т.д. Соответственно и план запросов у них будет простым и эффективным.
Предлагаю не полениться и привести здесь планы запросов: каждый от "своей" СУБД :)
Доберусь завтра до Informix - приведу из него. Очень хочется посмотреть, что же получится на разных СУБД.

Тестовый пример (модифицируйте под синтаксис своей СУБД)
Надеюсь синтаксис Informix SQL/SPL достаточно понятный

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
CREATE TABLE test_filters(
    field1 INTEGER
  , field2 INTEGER
  , field3 INTEGER
  , field4 INTEGER
  , field5 INTEGER
);

CREATE PROCEDURE fill_test_filters(p_count INTEGER)

  DEFINE i INTEGER;

  INSERT INTO test_filters(
    field1, field2, field3, field4, field5
  ) VALUES (
     1 ,  2 ,  3 ,  4 ,  5 
  );

  FOR i =  1  TO p_count 
    INSERT INTO test_filters(
      field1, field2, field3, field4, field5
    ) SELECT field1, field2 *  2 , field3 *  3 , field4 *  4 , field5 *  5 
        FROM test_filters;
  END FOR
END PROCEDURE;

EXECUTE PROCEDURE fill_test_filters( 20 ); -- МБ записей

CREATE INDEX idx_tst_field1 ON test_filters(field1);
CREATE INDEX idx_tst_field2 ON test_filters(field2);
CREATE INDEX idx_tst_field3 ON test_filters(field3);
CREATE INDEX idx_tst_field4 ON test_filters(field4);
CREATE INDEX idx_tst_field5 ON test_filters(field5);

CREATE INDEX idx_tst_field23 ON test_filters(field2, field3);

UPDATE STATISTICS HIGH FOR TABLE test_filters;

CREATE PROCEDURE run_test_filters(
    p_filter1 INTEGER
  , p_filter2 INTEGER
  , p_filter3 INTEGER
  , p_filter4 INTEGER
  , p_filter5 INTEGER
) RETURNING
    INT -- кол-во записей
  ;

  DEFINE v_cnt INTEGER;

  LET v_cnt = (
    SELECT COUNT(*)
      FROM test_filters
        WHERE (field1 = p_field1 OR p_field1 IS NULL)
          AND (field2 = p_field2 OR p_field2 IS NULL)
          AND (field3 = p_field3 OR p_field3 IS NULL)
          AND (field4 = p_field4 OR p_field4 IS NULL)
          AND (field5 = p_field5 OR p_field5 IS NULL)
  );

  RETURN v_cnt;
END PROCEDURE;
...
Рейтинг: 0 / 0
Формирование запроса
    #35959686
АнатоЛой
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tru55Тут есть еще другой аспект - повторное использование запроса (на примере Oracle).
Если все параметры сразу присутствуют в запросе, то запрос будет использован повторно, при динамике - каждый раз разбор и построение плана выполнения (hard parse).
Поэтому если время выборки значительно превышает время разбора (т.е. когда записей дофига) - это одно, если нет - это другое...
Я бы вёл речь не о динамическом формировании запроса с константами-фильтрами, а о "ручном" отбрасывании заведомо правдивых условий, а условия формировать таки параметризоваными. При N параметрах-фильтрах получаем аж N! (факториал) разных по тексту запросов...
...
Рейтинг: 0 / 0
Формирование запроса
    #35960789
АнатоЛой
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АнатоЛойПредлагаю не полениться и привести здесь планы запросов: каждый от "своей" СУБД :)
Доберусь завтра до Informix - приведу из него.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
Estimated Cost: 175804
Estimated # of Rows Returned: 1

  1) tolik.test_filters: SEQUENTIAL SCAN

        Filters: 
(((((tolik.test_filters.field5 = '<VAR>' OR '<VAR>' IS NULL ) 
AND (tolik.test_filters.field4 = '<VAR>' OR '<VAR>' IS NULL ) ) 
AND (tolik.test_filters.field3 = '<VAR>' OR '<VAR>' IS NULL ) ) 
AND (tolik.test_filters.field2 = '<VAR>' OR '<VAR>' IS NULL ) ) 
AND (tolik.test_filters.field1 = '<VAR>' OR '<VAR>' IS NULL ) )

Вот так :(
У кого лучше?
...
Рейтинг: 0 / 0
Формирование запроса
    #35961442
Фотография Ёш
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
это из-за prepare запроса, то есть из-за вызова его внутри функции, он там подготавливается при компиляции функции и больше не изменяется - поэтому оптимизатор не может выкинуть условия, он же не знает заранее какие параметры Вы ему передадите в функцию.

если же запрос выполнять напрямую, без функции, то имхо должен и у Вас догадаться, например:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
seb=> EXPLAIN ANALYZE select * from a where (f1 =  0  or  0  is null) and (f2 =  0  or  0  is null)
and (f3 =  0  or  0  is null) and (f4 =  0  or  0  is null);
                                         QUERY PLAN
---------------------------------------------------------------------------------------------
 Seq Scan on a  (cost= 0 . 00 .. 45 . 40  rows= 1  width= 16 ) (actual time= 0 . 003 .. 0 . 003  rows= 0  loops= 1 )
   Filter: ((f1 =  0 ) AND (f2 =  0 ) AND (f3 =  0 ) AND (f4 =  0 ))
 Total runtime:  0 . 043  ms
( 3  rows)

Время:  1 , 263  мс
seb=> EXPLAIN ANALYZE select * from a where (f1 =  0  or  0  is null) and (f2 = null or null is null)
and (f3 = null or null is null) and (f4 =  0  or  0  is null); 
                                         QUERY PLAN
---------------------------------------------------------------------------------------------
 Seq Scan on a  (cost= 0 . 00 .. 36 . 55  rows= 1  width= 16 ) (actual time= 0 . 002 .. 0 . 002  rows= 0  loops= 1 )
   Filter: ((f1 =  0 ) AND (f4 =  0 ))
 Total runtime:  0 . 041  ms
( 3  rows)

Время:  0 , 694  мс


--
„Истина — это вовсе не то, что можно убедительно доказать, это то, что
делает всё проще и понятнее“ — Антуан де Сент-Экзюпери
...
Рейтинг: 0 / 0
Формирование запроса
    #35961644
АнатоЛой
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ёш, проблема не в SP, а в параметризации запроса. Вы ведь показываете вариант непараметризованного запроса и заданный фильтр уже вписан в текст константой? Если да, смотрите ту же проблему кеша запросов, про которую писал tru55 (а также писал пресловутый "Ask" Tom - имхо, не мегаэксперт, но по крайней мере звезда среди экспертов - и профессионалу нужно точно представлять, почему он согласен либо не согласен с мнениями таких товарищей).
...
Рейтинг: 0 / 0
Формирование запроса
    #35971389
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Sybase ASA 10.

План при всех пустых параметрах выдает table scan, что правильно.
Код: plaintext
1.
2.
3.
4.
( Plan [ Total Cost Estimate:  13 . 107 , Estimated Cache Pages:  25006  ] 
  ( SingleRowGroupBy 
    ( TableScan test_filters )
  )
)

Устанавливаем p_field1=1. План снова выдает table scan, что тоже правильно (это поле имеет значение 1 для всех записей).
Код: plaintext
1.
2.
3.
4.
5.
( Plan [ Total Cost Estimate:  13 . 107 , Estimated Cache Pages:  25006  ] 
  ( SingleRowGroupBy 
    ( TableScan test_filters[  ( test_filters.field1 IS NOT NULL :  100 % Statistics | Bounded )  AND  
      ( test_filters.field1 =  1  :  100 % Statistics )  ] )
  )
)

Устанавливаем p_field1=1 и p_field2=32. Естественно оптимизатор взял индекс по второму полю, так как по первому значение присутствует во всех записях и условие field1 = 1 будет вынесено в постфильтр.
Код: plaintext
1.
2.
3.
4.
5.
6.
( Plan [ Total Cost Estimate:  0 . 060785 , Estimated Cache Pages:  25006  ] 
  ( SingleRowGroupBy 
    ( IndexScan test_filters idx_tst_field2[  
      ( test_filters.field1 IS NOT NULL :  100 % Statistics | Bounded )  AND  
      ( test_filters.field1 =  1  :  100 % Statistics )  ] )
  )
)

Тоже самое будет при установке или сбросе значений различных параметров - оптимизатор будет сначала переделывать запрос, выбрасывая не нужные его части (условия и соединения), далее по статистике, индексам, кол-ву свободной памяти, информации по текущему состоянию кеша и прочему, решать, какой план запроса будет оптимален.
...
Рейтинг: 0 / 0
Формирование запроса
    #35971425
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ёшэто из-за prepare запроса, то есть из-за вызова его внутри функции, он там подготавливается при компиляции функции и больше не изменяется - поэтому оптимизатор не может выкинуть условия, он же не знает заранее какие параметры Вы ему передадите в функцию.
Опять же от сервера зависит. В ASA к примеру запросы при компиляции не привязываются к процедурам или функциям, а хранятся в специальном кэше планов запросов. Сами же хранимки и функции компилируются в байт-код, который так же кэшируется в памяти для его быстрого получения и выполнения при вызове, но в нем хранится не план запроса, а сам запрос, который при вызове и будет искаться в кэше запросов или же при отсутствии подходящего создан оптимизатором.
...
Рейтинг: 0 / 0
Формирование запроса
    #35971990
АнатоЛой
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ASCRUSпри вызове и будет искаться в кэше запросов или же при отсутствии подходящего создан оптимизатором.
Запрос оптимизируется до того, как известны параметры. Или ASA какие-то доп.приёмы применяет по оптимизации после того, как стали известны значения параметров?
...
Рейтинг: 0 / 0
Формирование запроса
    #35972406
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АнатоЛойЗапрос оптимизируется до того, как известны параметры. Или ASA какие-то доп.приёмы применяет по оптимизации после того, как стали известны значения параметров?
В ASA запрос оптимизируется перед непосредственным его выполнением, то есть после того, как известны параметры.
...
Рейтинг: 0 / 0
Формирование запроса
    #35972870
АнатоЛой
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ASCRUSАнатоЛойЗапрос оптимизируется до того, как известны параметры. Или ASA какие-то доп.приёмы применяет по оптимизации после того, как стали известны значения параметров?
В ASA запрос оптимизируется перед непосредственным его выполнением, то есть после того, как известны параметры.
А в кеше какой запрос лежит: с именем параметра или со значением?
Если с именем параметра, то типа экономим только на синтаксическом анализе - а планы выбираем на этапе выполнения, когда значения параметров известны. А когда варианты планов СТРОИМ: когда помещаем в кеш, когда известны значения параметров или ещё как?
...
Рейтинг: 0 / 0
Формирование запроса
    #35973554
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АнатоЛойASCRUSАнатоЛойЗапрос оптимизируется до того, как известны параметры. Или ASA какие-то доп.приёмы применяет по оптимизации после того, как стали известны значения параметров?
В ASA запрос оптимизируется перед непосредственным его выполнением, то есть после того, как известны параметры.
А в кеше какой запрос лежит: с именем параметра или со значением?
Если с именем параметра, то типа экономим только на синтаксическом анализе - а планы выбираем на этапе выполнения, когда значения параметров известны. А когда варианты планов СТРОИМ: когда помещаем в кеш, когда известны значения параметров или ещё как?
Насчет того, что лежит в кэше ничего не скажу - это только сами разработчики ASA могут рассказать. Кэшем запросов можно управлять через опцию, в которой можно указать максимально допустимое кол-во кэшируемых запросов (или можно вообще его отключить). Проверить тоже не представляется возможным - у ASA оптимизатор слишком шустро генерит планы запросов даже при больших нагрузках (Watcom как никак, у них всегда компиляторы и виртуальные машины быстро бегали). Я лично могу предположить, что все таки в кэше хранится с именем параметра, так как планы запросов у ASA всегда актуальны на момент текущего состояния статистики таблиц, которая автопилотом обновляется на DML операторах. Иначе бы могли возникнуть ситуации, что оптимизатор использует не подходящий план запроса (когда например выполнили запрос, влили в таблицу существенный объем записей и снова выполнили тот же запрос).
...
Рейтинг: 0 / 0
Формирование запроса
    #35973694
АнатоЛой
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Потому что по первому вашему посту непонятно, вы ХП делали, запрос с параметрами запускали или запрос с константами...
Если не с параметрами, можете запустить запрос именно с параметрами, а не константами, и показать информацию о выборе плана?
...
Рейтинг: 0 / 0
Формирование запроса
    #35973726
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АнатоЛойПотому что по первому вашему посту непонятно, вы ХП делали, запрос с параметрами запускали или запрос с константами...
Если не с параметрами, можете запустить запрос именно с параметрами, а не константами, и показать информацию о выборе плана?
Гм, как Вы и просили, я трансформировал Ваш скрипт в аналог Асашного и выдал план выполнения запросов с параметрами. Никаких констант там нет.
...
Рейтинг: 0 / 0
Формирование запроса
    #35973836
АнатоЛой
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ASCRUS, ок, пасибо. Остальное своё любопытство удовлетворять за ваш счёт уже неэтично :).
...
Рейтинг: 0 / 0
Формирование запроса
    #35974049
Фотография ASCRUS
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
АнатоЛойASCRUS, ок, пасибо. Остальное своё любопытство удовлетворять за ваш счёт уже неэтично :).
Да не за что :) Мне самому интересно разбираться в работе оптимизаторов различных серверов. У Sybase ASA кстати оптимизатор близок по логике работы к оптимизаторам прочих РСУБД и в 90% случаев он предсказуем, выбирает оптимальные планы запросов в зависимости от выставленных для сессии опций предпочтительной модели поведения (OLTP/OLAP, фоновое выполнение, уровень оптимизации, максимальное задействованное кол-во процессоров для параллельного выполнения частей запроса и т.д.). К примеру, у Sybase IQ, оптимизатор вообще своеобразный, начиная от своеобразных типов индексов и заканчивая тем, что в базе даже нет такого понятия, как статистика полей таблиц. Его работа для меня вообще загадка природы, хотя с точки зрения оптимизации планы запросов он генерит неплохие.
...
Рейтинг: 0 / 0
25 сообщений из 25, страница 1 из 1
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Формирование запроса
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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