L>Не поможет. Можно хоть обвешаться индексами, но если оптимизатор построил план, в котором используется индекс по полю A, а фактически ты ищешь по B, то индекс не поможет.
Oracle и MSSQL можно пнуть в запросе на прямое использование индексов.
Здравствуйте, VGn, Вы писали:
L>>Не поможет. Можно хоть обвешаться индексами, но если оптимизатор построил план, в котором используется индекс по полю A, а фактически ты ищешь по B, то индекс не поможет.
VGn>Oracle и MSSQL можно пнуть в запросе на прямое использование индексов.
Ну покажи, как в запросе пнуть на использование индекса в зависимости от значения параметра.
L>>>Не поможет. Можно хоть обвешаться индексами, но если оптимизатор построил план, в котором используется индекс по полю A, а фактически ты ищешь по B, то индекс не поможет.
VGn>>Oracle и MSSQL можно пнуть в запросе на прямое использование индексов.
L>Ну покажи, как в запросе пнуть на использование индекса в зависимости от значения параметра.
А причём тут значение параметра? Вопрос ставился: параметр A vs параметр B.
Здравствуйте, VGn, Вы писали:
VGn>>>Oracle и MSSQL можно пнуть в запросе на прямое использование индексов.
L>>Ну покажи, как в запросе пнуть на использование индекса в зависимости от значения параметра.
VGn>А причём тут значение параметра? Вопрос ставился: параметр A vs параметр B.
Такой вопрос не ставился. Прочитай ветку полностью до корня.
Здравствуйте, VGn, Вы писали:
VGn>>>Oracle и MSSQL можно пнуть в запросе на прямое использование индексов.
VGn>Oracle VGn>MSSQL 1 VGn>MSSQL 2
Здорово, что ты умеешь пользоваться гуглом.
Но проблема не в отсутствии возможности указать оптимизатору какой индекс использовать, а в том, что план жостко привязан к тексту запросу. И если в плане стоит использование индекса по A, а параметры запроса таковы, что искать нужно не по A, а по B, то хоть тресни, а не заставишь сервер искать по B.
L>Здорово, что ты умеешь пользоваться гуглом. L>Но проблема не в отсутствии возможности указать оптимизатору какой индекс использовать, а в том, что план жостко привязан к тексту запросу. И если в плане стоит использование индекса по A, а параметры запроса таковы, что искать нужно не по A, а по B, то хоть тресни, а не заставишь сервер искать по B.
А вот ты наверное не умеешь даже читать по ссылкам. Хинтование управляет построением плана запроса.
L>>>Ну покажи, как в запросе пнуть на использование индекса в зависимости от значения параметра.
VGn>>А причём тут значение параметра? Вопрос ставился: параметр A vs параметр B.
L>Такой вопрос не ставился. Прочитай ветку полностью до корня.
Ничего кроме вопроса наличия ограничений я не нашёл.
Здравствуйте, VGn, Вы писали:
VGn>А вот ты наверное не умеешь даже читать по ссылкам. Хинтование управляет построением плана запроса.
Ты абсолютно прав, хинтом можно "поправить" план. Проблема в том, что после этого план жостко привязан к запросу. И если в плане стоит использование индекса по A, а параметры запроса таковы, что искать нужно не по A, а по B, то хоть тресни, а не заставишь сервер искать по B.
VGn>>А вот ты наверное не умеешь даже читать по ссылкам. Хинтование управляет построением плана запроса.
L>Ты абсолютно прав, хинтом можно "поправить" план. Проблема в том, что после этого план жёстко привязан к запросу.
А не это ли цель?
L>И если в плане стоит использование индекса по A, а параметры запроса таковы, что искать нужно не по A, а по B, то хоть тресни, а не заставишь сервер искать по B.
Копипастишь?
Или считаешь, что запрос не должен описывать, что тебе в действительности надо?
Здравствуйте, VGn, Вы писали:
VGn>>>А вот ты наверное не умеешь даже читать по ссылкам. Хинтование управляет построением плана запроса.
L>>Ты абсолютно прав, хинтом можно "поправить" план. Проблема в том, что после этого план жёстко привязан к запросу.
Спасибо за исправление ошибок. Но как я помню, это является нарушением правил поведения на этом форуме.
VGn>А не это ли цель?
Цель — получить быстрый код.
L>>И если в плане стоит использование индекса по A, а параметры запроса таковы, что искать нужно не по A, а по B, то хоть тресни, а не заставишь сервер искать по B.
VGn>Копипастишь?
Что делать, приходится.
VGn>Или считаешь, что запрос не должен описывать, что тебе в действительности надо?
L>Спасибо за исправление ошибок. Но как я помню, это является нарушением правил поведения на этом форуме.
Исправление ошибок не может быть нарушением. Иначе будет хаос.
Нарушением являются упрёки в безграмотности, а я и не упрекал.
VGn>>А не это ли цель?
L>Цель — получить быстрый код.
(-)
Цель — добиться быстрого ответа от базы на запрос. Код — это частности.
Если вы отладили запрос на больших объёмах данных, то при неизменном плане он будет работать так же быстро (но не быстрее )
L>>>И если в плане стоит использование индекса по A, а параметры запроса таковы, что искать нужно не по A, а по B, то хоть тресни, а не заставишь сервер искать по B.
VGn>>Копипастишь?
L>Что делать, приходится.
VGn>>Или считаешь, что запрос не должен описывать, что тебе в действительности надо?
L>Этой фразы я не понял. Что ты имеешь в виду?
Я имел в виду, что если тебе надо условие на B, ты делаешь условие на В.
А если на А, то, соответственно, — на А.
И в запросе уже описано, что ты хочешь. А значит такой запрос можно с большой вероятностью тюнинговать так, чтобы и база поняла, что ты хочешь. И тогда всё будет работать максимально быстро.
Но на гибких системах это трудно. Думаю, это даже искусство.
Здравствуйте, VGn, Вы писали:
VGn>>>А не это ли цель?
L>>Цель — получить быстрый код.
VGn>(-) VGn>Цель — добиться быстрого ответа от базы на запрос. Код — это частности. VGn>Если вы отладили запрос на больших объёмах данных, то при неизменном плане он будет работать так же быстро (но не быстрее )
Нет, это не так. Для разных параметров запроса оптимальный план будет отличаться.
Подумай, над таким запросом:
SELECT * FROM tbl WHERE (@A IS NULL OR tbl.A = @A) AND (@B IS NULL OR tbl.B = @B)
Если @A = 100, a @B = NULL, то очевидно, что должен использоваться индекс по полю tbl.A
Если @A = NULL, a @B = 100, то очевидно, что должен использоваться индекс по полю tbl.B
В плане же всегда будет стоять первым или индекс по A или индекс по B, т.е. в любом случае будет сочетание параметров, для которого выбраный план не лучший.
VGn>Я имел в виду, что если тебе надо условие на B, ты делаешь условие на В. VGn>А если на А, то, соответственно, — на А.
Мне нужно условие на A, а Маше из соседнего отдела — на B.
VGn>И в запросе уже описано, что ты хочешь. А значит такой запрос можно с большой вероятностью тюнинговать так, чтобы и база поняла, что ты хочешь. И тогда всё будет работать максимально быстро.
Не будет. Объяснение — выше.
VGn>Но на гибких системах это трудно. Думаю, это даже искусство.
L>Нет, это не так. Для разных параметров запроса оптимальный план будет отличаться. L>Подумай, над таким запросом: L>
L>SELECT * FROM tbl WHERE (@A IS NULL OR tbl.A = @A) AND (@B IS NULL OR tbl.B = @B)
L>
L>Если @A = 100, a @B = NULL, то очевидно, что должен использоваться индекс по полю tbl.A L>Если @A = NULL, a @B = 100, то очевидно, что должен использоваться индекс по полю tbl.B
Я уже таких запросов давно не пишу. Это запрос — два в одном. Динамические запросы RULEZZZ.
У меня сейчас в одной процедурке генерится запрос на осоновании около 30 фильтров.
И ничего. Вполне себе летает. Сначала из лени делал тоже с условиями на NULL, но так он еле ползал.
L>В плане же всегда будет стоять первым или индекс по A или индекс по B, т.е. в любом случае будет сочетание параметров, для которого выбраный план не лучший.
Безусловно. Но во-первых идеала нет, а во-вторых индексы всё-равно будут использоваться.
Здравствуйте, VGn, Вы писали:
L>>Если @A = 100, a @B = NULL, то очевидно, что должен использоваться индекс по полю tbl.A L>>Если @A = NULL, a @B = 100, то очевидно, что должен использоваться индекс по полю tbl.B
VGn>Я уже таких запросов давно не пишу. Это запрос — два в одном.
И чего тогда минусов наставил?
VGn>Динамические запросы RULEZZZ.
Динамические запросы — SUXX. Попрбуй LINQ
VGn>У меня сейчас в одной процедурке генерится запрос на осоновании около 30 фильтров. VGn>И ничего. Вполне себе летает. Сначала из лени делал тоже с условиями на NULL, но так он еле ползал.
Ползал он как раз по той причине, что и была описана.
L>>В плане же всегда будет стоять первым или индекс по A или индекс по B, т.е. в любом случае будет сочетание параметров, для которого выбраный план не лучший.
VGn>Безусловно. Но во-первых идеала нет, а во-вторых индексы всё-равно будут использоваться.
Здравствуйте, J_K, Вы писали:
J_K>Здравствуйте. J_K>Имеется форма поиска некоторого товара. Например, это могут быть палатки. Например, требуется выбрать кемпинговую палатку на 4 человек с одним тамбуром. Другие параметры (их может быть сколько угодно каких угодно) неважны. Как обработать данные? Т.е. порядок действий примерно таков: J_K>1. Пользователь указывает значение параметров, выбранных произвольно (т.е. не все параметры могут быть указаны) J_K>2. Данные отправляются на сервер и там обработчик должен отправить запрос к БД. J_K>3??? Кто формирует запрос? Ясно, что это не может быть хранимая процедура, поскольку заранее неизвестно, какие параметры будут указаны. Можно составить запрос (строку) программным образом типа "если этот параметр присутствует, то включить его в строку, иначе нет" — но тогда получится запутанный и уродский код — потому что этот параметр надо указывать дважды, даже трижды — при вводе параметров, в самом запросе и потом при выводе данных. Чуть более красиво получается если использовать LINQ, но у меня нет уверенности, что так можно (и как?). В-общем, непонятно, как делать, кроме того, возможно, на момент запуска код linq ничего не будет знать о данной сущности (если например, они добавляются динамически). Если использовать орм LLBLGen, то проблема решается легче, там просто добавляешь или не добавляешь некий фильтр, а уж он сам формирует запрос. Но эта орм недешевое удовольствие и пока ее использование не планируется. J_K>Какова вообще правильная тактика для решения данной задачи? Особенно прошу помочь тех, кто делал что-то подобное. J_K>Спасибо
Посмотри у Фаулера в "Архитектуре корпоративных программных приложений" шаблон "Query object". Без излишеств, типа отображения поля класса <-> имена полей таблицы, вполне ничего для таких задач.
Здравствуйте, knst, Вы писали: K>Ну не сказал бы что генерация sql на лету будет быстрее.
А зря. Генерация работает со скоростью CPU, а поиск — со скоростью HDD. K> Параметров ограниченное количество, сделать правильные индексы не сложно.
Правильно. А вот построить план запроса с использованием этих индексов — сложно.
Предикат вида PARAM=@PARAM OR @PARAM is NULL — практически однозначно table scan. K>Да и если речь идет о товарах в магазине, то объем данных небольшой, можно и не заморачиваться с оптимизацией — поиск идет по максимум 10000 записей, это не объем для БД, все будет летать даже если запрос кривой.
Это капитански-очевидное утверждение. Если игнорировать производительность, то все варианты, включая подъем всех записей в память аппсервера и ручной перебор, будут равнозначными.
А если о ней хоть на минуточку задуматься, то динамическая генерация SQL рулит однозначно.
Ей пренебрегать можно только в тех случаях, когда под рукой нет адекватных инструментов (вроде Linq), и стабильность кода трудно обеспечить.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, knst, Вы писали:
K>В таком случае можно поизобретать велосипеды например ввести понятие хэш кода расчитывающегося на основании полей и делать выборку в два этапа — сначала на стороне сервера вычисляем хэш код фильтруем по нему а уже в пределах найденного уточняем поиск или взять готовый велосипед на базе MapReduce (например Aster nCluster или Hadoop).
Совершенно непонятно, что может заставить изобретать такой велосипед, в присутствии идеально подходящих коробочных решений. K>Хотя опять же, что значит очень много... на нескольких миллионах БД по прежнему вполне шустро выполняет запросы.
Надо полагать, опыта работы с веб-проектами с ненулевой нагрузкой у тебя нет?
Это с точки зрения отдельного пользователя 800мс на запрос ничуть не отличаются от 10мс. А с точки зрения администратора сервера, первое — это 100% загрузки SQL сервера, а второе — 12%. K>Возможно я не прав, но у меня сложилось впечатление, что ты пытаешься решить проблему , которая еще не возникла, оптимизировать стоит уже написанные запросы если они тормозят, а не пытаться изначально усложнить систему с целью повысить быстродействие. Ботлнек может оказаться совсем не на стороне базы.
У меня сложилось впечатление, что ты не понимаешь, о чём говоришь. Сначала ты предлагаешь пессимизацию (написание плохого универсального запроса); затем предлагаешь непроизводительное усложнение кода. Ты вот про хеш упомянул — предположим, такой "хеш" таки можно построить. Откуда взялась идея, что он даст улучшение производительности по сравнению с использованием классического встроенного B-Tree индекса для поиска вот по такому предикату:
select * from Tents where maxCount = 4 and CoveredExits = 1
?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, VGn, Вы писали:
VGn>>>Oracle и MSSQL можно пнуть в запросе на прямое использование индексов.
VGn>Oracle VGn>MSSQL 1 VGn>MSSQL 2
Это не имеет никакого отношения к предмету разговора.
Улучшить вот такой запрос
select * from Tents where (MaxPersons = @MaxPersons or @MaxPersons is null) AND (ExitsCount = @ExitsCount or @ExitsCount is null)
ты не сможешь никакими хинтами. Ровно потому, что в зависимости от значений параметров запроса, нужно использовать разные индексы.
Если же ты генерируешь запрос динамически, отдельно для каждых значений параметров, то никакие хинты нахрен не нужны — так и пиши:
select * from Tents where MaxPersons = @MaxPersons
Сервер сам разберётся, какие индексы применять.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.