Здравствуйте, J_K, Вы писали:
J_K>Какова вообще правильная тактика для решения данной задачи? Особенно прошу помочь тех, кто делал что-то подобное.
Самая правильная тактика не делать такой уродский поиск. Или хотыб не называть это поиском.
Вы же гуглом пользуетесь, сколько там полей воода и кнопок?
И если в гугле написать "кемпинговая палатка на 4 человек с одним тамбуром", то они найдет именно такую палатку.
Здравствуйте, knst, Вы писали:
L>>Только вот скорость исполнения этого запроса будет далека от оптимальной
K>Ну не сказал бы что генерация sql на лету будет быстрее.
Гораздо быстрее.
K>Параметров ограниченное количество, сделать правильные индексы не сложно.
Не поможет. Можно хоть обвешаться индексами, но если оптимизатор построил план, в котором используется индекс по полю A, а фактически ты ищешь по B, то индекс не поможет.
Здравствуйте, 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". Без излишеств, типа отображения поля класса <-> имена полей таблицы, вполне ничего для таких задач.
Здравствуйте, J_K, Вы писали:
L>>Именно это приведенный код и делает.
J_K>Не могли бы вы использовать более понятные обозначения? Скажем, пусть тип товары будет Tents, а параметры parameter1, parameter2. А то я сколько ни пялюсь, не могу увидеть в вашем коде несколько параметров. Спасиб
Здравствуйте, 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.
Здравствуйте, 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>Безусловно. Но во-первых идеала нет, а во-вторых индексы всё-равно будут использоваться.
Здравствуйте, 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>Но на гибких системах это трудно. Думаю, это даже искусство.
Здравствуйте, J_K, Вы писали:
J_K>Чуть более красиво получается если использовать LINQ, но у меня нет уверенности, что так можно (и как?). В-общем, непонятно, как делать, кроме того, возможно, на момент запуска код linq ничего не будет знать о данной сущности (если например, они добавляются динамически). Если использовать орм LLBLGen, то проблема решается легче, там просто добавляешь или не добавляешь некий фильтр, а уж он сам формирует запрос.
J_K>Мне кажется, тут не совсем так. Псевдокод должен быть примерно таким: J_K>if (@param1 != null) J_K> where += param1 == @param1 J_K>if (param2 != null) J_K> where += param2 == @param2
Нет, вы ошибаетесь. Код буде именно такой как написано выше.
J_K>Ну и так далее. Честно, я плохо знаю возможности linq с этой т.з. Т.е задача состоит в том, чтобы составить запрос, когда состав и значение параметров заранее неизвестны.
Здравствуйте, VGn, Вы писали:
VGn>А вот ты наверное не умеешь даже читать по ссылкам. Хинтование управляет построением плана запроса.
Ты абсолютно прав, хинтом можно "поправить" план. Проблема в том, что после этого план жостко привязан к запросу. И если в плане стоит использование индекса по A, а параметры запроса таковы, что искать нужно не по A, а по B, то хоть тресни, а не заставишь сервер искать по B.
Здравствуйте.
Имеется форма поиска некоторого товара. Например, это могут быть палатки. Например, требуется выбрать кемпинговую палатку на 4 человек с одним тамбуром. Другие параметры (их может быть сколько угодно каких угодно) неважны. Как обработать данные? Т.е. порядок действий примерно таков:
1. Пользователь указывает значение параметров, выбранных произвольно (т.е. не все параметры могут быть указаны)
2. Данные отправляются на сервер и там обработчик должен отправить запрос к БД.
3??? Кто формирует запрос? Ясно, что это не может быть хранимая процедура, поскольку заранее неизвестно, какие параметры будут указаны. Можно составить запрос (строку) программным образом типа "если этот параметр присутствует, то включить его в строку, иначе нет" — но тогда получится запутанный и уродский код — потому что этот параметр надо указывать дважды, даже трижды — при вводе параметров, в самом запросе и потом при выводе данных. Чуть более красиво получается если использовать LINQ, но у меня нет уверенности, что так можно (и как?). В-общем, непонятно, как делать, кроме того, возможно, на момент запуска код linq ничего не будет знать о данной сущности (если например, они добавляются динамически). Если использовать орм LLBLGen, то проблема решается легче, там просто добавляешь или не добавляешь некий фильтр, а уж он сам формирует запрос. Но эта орм недешевое удовольствие и пока ее использование не планируется.
Какова вообще правильная тактика для решения данной задачи? Особенно прошу помочь тех, кто делал что-то подобное.
Спасибо
Life is very short and there's no time
for fussing and fighting... (C) Paul McCartney & John Lennon
Здравствуйте, J_K, Вы писали:
J_K>Здравствуйте. J_K>Имеется форма поиска некоторого товара. Например, это могут быть палатки. Например, требуется выбрать кемпинговую палатку на 4 человек с одним тамбуром. Другие параметры (их может быть сколько угодно каких угодно) неважны. Как обработать данные? Т.е. порядок действий примерно таков: J_K>1. Пользователь указывает значение параметров, выбранных произвольно (т.е. не все параметры могут быть указаны) J_K>2. Данные отправляются на сервер и там обработчик должен отправить запрос к БД. J_K>3??? Кто формирует запрос? Ясно, что это не может быть хранимая процедура, поскольку заранее неизвестно, какие параметры будут указаны. Можно составить запрос (строку) программным образом типа "если этот параметр присутствует, то включить его в строку, иначе нет" — но тогда получится запутанный и уродский код — потому что этот параметр надо указывать дважды, даже трижды — при вводе параметров, в самом запросе и потом при выводе данных. Чуть более красиво получается если использовать LINQ, но у меня нет уверенности, что так можно (и как?). В-общем, непонятно, как делать, кроме того, возможно, на момент запуска код linq ничего не будет знать о данной сущности (если например, они добавляются динамически). Если использовать орм LLBLGen, то проблема решается легче, там просто добавляешь или не добавляешь некий фильтр, а уж он сам формирует запрос. Но эта орм недешевое удовольствие и пока ее использование не планируется. J_K>Какова вообще правильная тактика для решения данной задачи? Особенно прошу помочь тех, кто делал что-то подобное. J_K>Спасибо
Например можно передавать NULL в тех местах где параметр не задан а в where: PARAM=@PARAM OR @PARAM is NULL
Вряд ли нужно искать палатки для которых не известно кол-во мест(если нужно, запрос будет чутьсложнее но тож решаемо)
И кстати лучше это делать не запросом а хранимкой, так оно со всех сторон вернее — быстрее, нет хардкода запроса и грязи в коде, ошибки в запросе можно исправить не передеплоивая код, быстрее наконец.
Здравствуйте, gandjustas, Вы писали:
G>Здравствуйте, J_K, Вы писали:
J_K>>Какова вообще правильная тактика для решения данной задачи? Особенно прошу помочь тех, кто делал что-то подобное.
G>Самая правильная тактика не делать такой уродский поиск. Или хотыб не называть это поиском.
Ну скажите это ребятам из yandex.market. У них это реализовано именно так и работает.
G>Вы же гуглом пользуетесь, сколько там полей воода и кнопок? G>И если в гугле написать "кемпинговая палатка на 4 человек с одним тамбуром", то они найдет именно такую палатку.
Увы, ничего ваш гугль не найдет. Проверено на себе лично безуспешными поисками некоторых вещей.
Во-вторых, лично я не люблю писать. Да, я не люблю писать! Я могу ошибиться, я могу забыть что-то. Если поиск знает все параметры, гораздо проще сделать несколько кликов, чем вписывать. Попробуйте написать "кемпинговая палатка на 4 человек с одним тОмбуром" и вы получите в ответ молчание. В данном топике обсуждаются не плюсы-минусы данного подхода, а как это реализовать. Давайте уж придерживаться темы, что ли.
Life is very short and there's no time
for fussing and fighting... (C) Paul McCartney & John Lennon
Здравствуйте, knst, Вы писали:
K>Здравствуйте, J_K, Вы писали:
J_K>>Здравствуйте. J_K>>Имеется форма поиска некоторого товара. Например, это могут быть палатки. Например, требуется выбрать кемпинговую палатку на 4 человек с одним тамбуром. Другие параметры (их может быть сколько угодно каких угодно) неважны. Как обработать данные? Т.е. порядок действий примерно таков: J_K>>1. Пользователь указывает значение параметров, выбранных произвольно (т.е. не все параметры могут быть указаны) J_K>>2. Данные отправляются на сервер и там обработчик должен отправить запрос к БД. J_K>>3??? Кто формирует запрос? Ясно, что это не может быть хранимая процедура, поскольку заранее неизвестно, какие параметры будут указаны. Можно составить запрос (строку) программным образом типа "если этот параметр присутствует, то включить его в строку, иначе нет" — но тогда получится запутанный и уродский код — потому что этот параметр надо указывать дважды, даже трижды — при вводе параметров, в самом запросе и потом при выводе данных. Чуть более красиво получается если использовать LINQ, но у меня нет уверенности, что так можно (и как?). В-общем, непонятно, как делать, кроме того, возможно, на момент запуска код linq ничего не будет знать о данной сущности (если например, они добавляются динамически). Если использовать орм LLBLGen, то проблема решается легче, там просто добавляешь или не добавляешь некий фильтр, а уж он сам формирует запрос. Но эта орм недешевое удовольствие и пока ее использование не планируется. J_K>>Какова вообще правильная тактика для решения данной задачи? Особенно прошу помочь тех, кто делал что-то подобное. J_K>>Спасибо
K>Например можно передавать NULL в тех местах где параметр не задан а в where: PARAM=@PARAM OR @PARAM is NULL K>Вряд ли нужно искать палатки для которых не известно кол-во мест(если нужно, запрос будет чутьсложнее но тож решаемо) K>И кстати лучше это делать не запросом а хранимкой, так оно со всех сторон вернее — быстрее, нет хардкода запроса и грязи в коде, ошибки в запросе можно исправить не передеплоивая код, быстрее наконец.
В том-то и дело, что нужно искать и палатки, для которых неизвестно количество мест. Может, я хочу прикинуть разницу между палаткой на трех и четырех человек. Т.е. суть задачи в том, что заранее набор параметров неизвестен. Соглашусь, что параметров также не должно быть слишком много, но даже если их будет в пределах десяти, и они будут разные — например, один параметр — это строка, другой — значение (списка), третий — в промежутке от N до M — это сильно усложняет задачу в целом.
Life is very short and there's no time
for fussing and fighting... (C) Paul McCartney & John Lennon
Здравствуйте, knst, Вы писали:
K>И кстати лучше это делать не запросом а хранимкой, так оно со всех сторон вернее — быстрее, нет хардкода запроса и грязи в коде, ошибки в запросе можно исправить не передеплоивая код, быстрее наконец.
Только вот скорость исполнения этого запроса будет далека от оптимальной
Здравствуйте, J_K, Вы писали:
J_K>Здравствуйте. J_K>Имеется форма поиска некоторого товара. Например, это могут быть палатки. Например, требуется выбрать кемпинговую палатку на 4 человек с одним тамбуром. Другие параметры (их может быть сколько угодно каких угодно) неважны. Как обработать данные? Т.е. порядок действий примерно таков:
Тут всё просто и понятно.
Хранилище данных или объектная модель должны предоставлять свое метаописание в таком качестве, чтобы автомат мог по метаописанию 1) построить пользователю гуй формы запроса 2) смастерить дерево выражений параметров поиска и фильтрации и скормить его автомату, выполняющему запрос. Этот функционал отлично реализован, например, в 1С-ке.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, J_K, Вы писали:
J_K>>Чуть более красиво получается если использовать LINQ, но у меня нет уверенности, что так можно (и как?). В-общем, непонятно, как делать, кроме того, возможно, на момент запуска код linq ничего не будет знать о данной сущности (если например, они добавляются динамически). Если использовать орм LLBLGen, то проблема решается легче, там просто добавляешь или не добавляешь некий фильтр, а уж он сам формирует запрос.
L>На LINQ-е будет ровно так же: L>
Мне кажется, тут не совсем так. Псевдокод должен быть примерно таким:
if (@param1 != null)
where += param1 == @param1
if (param2 != null)
where += param2 == @param2
Ну и так далее. Честно, я плохо знаю возможности linq с этой т.з. Т.е задача состоит в том, чтобы составить запрос, когда состав и значение параметров заранее неизвестны.
Life is very short and there's no time
for fussing and fighting... (C) Paul McCartney & John Lennon
J_K>>Мне кажется, тут не совсем так. Псевдокод должен быть примерно таким: J_K>>if (@param1 != null) J_K>> where += param1 == @param1 J_K>>if (param2 != null) J_K>> where += param2 == @param2
L>Нет, вы ошибаетесь. Код буде именно такой как написано выше.
J_K>>Ну и так далее. Честно, я плохо знаю возможности linq с этой т.з. Т.е задача состоит в том, чтобы составить запрос, когда состав и значение параметров заранее неизвестны.
L>Именно это приведенный код и делает.
Не могли бы вы использовать более понятные обозначения? Скажем, пусть тип товары будет Tents, а параметры parameter1, parameter2. А то я сколько ни пялюсь, не могу увидеть в вашем коде несколько параметров. Спасиб
Life is very short and there's no time
for fussing and fighting... (C) Paul McCartney & John Lennon
Здравствуйте, baranovda, Вы писали:
B>Здравствуйте, J_K, Вы писали:
J_K>>Здравствуйте. J_K>>Имеется форма поиска некоторого товара. Например, это могут быть палатки. Например, требуется выбрать кемпинговую палатку на 4 человек с одним тамбуром. Другие параметры (их может быть сколько угодно каких угодно) неважны. Как обработать данные? Т.е. порядок действий примерно таков:
B>Тут всё просто и понятно. B>Хранилище данных или объектная модель должны предоставлять свое метаописание в таком качестве, чтобы автомат мог по метаописанию 1) построить пользователю гуй формы запроса 2) смастерить дерево выражений параметров поиска и фильтрации и скормить его автомату, выполняющему запрос. Этот функционал отлично реализован, например, в 1С-ке.
Допускаю, что в 1с реализовано если не все, то большинство из того, что мне нужно... но использование 1с исключено по ряду причин.
Life is very short and there's no time
for fussing and fighting... (C) Paul McCartney & John Lennon
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, J_K, Вы писали:
L>>>Именно это приведенный код и делает.
J_K>>Не могли бы вы использовать более понятные обозначения? Скажем, пусть тип товары будет Tents, а параметры parameter1, parameter2. А то я сколько ни пялюсь, не могу увидеть в вашем коде несколько параметров. Спасиб
L>
А у меня еще такой вопрос созрел (почти безотносительно текущего) — есть два подхода. Первый — использовать готовую ХП, второй — генерировать ее на лету. Как вы думаете, какой подход лучше с т.з. производительности?
Life is very short and there's no time
for fussing and fighting... (C) Paul McCartney & John Lennon
Здравствуйте, J_K, Вы писали:
J_K>А у меня еще такой вопрос созрел (почти безотносительно текущего) — есть два подхода. Первый — использовать готовую ХП, второй — генерировать ее на лету. Как вы думаете, какой подход лучше с т.з. производительности?
Второй вариант лучше, т.к. производительность запросов зависит в частности от того, насколько у них "хороший" план.
Если у вас один запрос на все случаи (как в варианте с хранимкой), то и план будет один и получить хороший план для любого набора входных параметров не получится.
Если же вы генерите запросы на лету (как в варианте с LINQ-ом), то для разного набора параметров фильтрации будут сформированы разные запросы и план выполнения будет лучше.
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, J_K, Вы писали:
J_K>>А у меня еще такой вопрос созрел (почти безотносительно текущего) — есть два подхода. Первый — использовать готовую ХП, второй — генерировать ее на лету. Как вы думаете, какой подход лучше с т.з. производительности?
L>Второй вариант лучше, т.к. производительность запросов зависит в частности от того, насколько у них "хороший" план. L>Если у вас один запрос на все случаи (как в варианте с хранимкой), то и план будет один и получить хороший план для любого набора входных параметров не получится. L>Если же вы генерите запросы на лету (как в варианте с LINQ-ом), то для разного набора параметров фильтрации будут сформированы разные запросы и план выполнения будет лучше.
Хм... интересно, подумаю. Спасибо
Life is very short and there's no time
for fussing and fighting... (C) Paul McCartney & John Lennon
Здравствуйте, Lloyd, Вы писали:
L>Здравствуйте, knst, Вы писали:
K>>И кстати лучше это делать не запросом а хранимкой, так оно со всех сторон вернее — быстрее, нет хардкода запроса и грязи в коде, ошибки в запросе можно исправить не передеплоивая код, быстрее наконец.
L>Только вот скорость исполнения этого запроса будет далека от оптимальной
Ну не сказал бы что генерация sql на лету будет быстрее. Параметров ограниченное количество, сделать правильные индексы не сложно.
Да и если речь идет о товарах в магазине, то объем данных небольшой, можно и не заморачиваться с оптимизацией — поиск идет по максимум 10000 записей, это не объем для БД, все будет летать даже если запрос кривой. Если б объемы были большими порекомендовал бы OLAP (Хотя тут как с нейросетями — идея кажется красивой и всеобъемлющей на первый взгляд а как пытаешься копнуть глубже выясняется что подходит только для небольшого кол-ва частных случаев).
Здравствуйте, knst, Вы писали:
K>Здравствуйте, Lloyd, Вы писали:
L>>Здравствуйте, knst, Вы писали:
K>>>И кстати лучше это делать не запросом а хранимкой, так оно со всех сторон вернее — быстрее, нет хардкода запроса и грязи в коде, ошибки в запросе можно исправить не передеплоивая код, быстрее наконец.
L>>Только вот скорость исполнения этого запроса будет далека от оптимальной
K>Ну не сказал бы что генерация sql на лету будет быстрее. Параметров ограниченное количество, сделать правильные индексы не сложно. K>Да и если речь идет о товарах в магазине, то объем данных небольшой, можно и не заморачиваться с оптимизацией — поиск идет по максимум 10000 записей, это не объем для БД, все будет летать даже если запрос кривой. Если б объемы были большими порекомендовал бы OLAP (Хотя тут как с нейросетями — идея кажется красивой и всеобъемлющей на первый взгляд а как пытаешься копнуть глубже выясняется что подходит только для небольшого кол-ва частных случаев).
Речь идет о товарах, но не в магазине — сервис вроде поисковой системы. Мы сами ничего не продаем, а только предоставляем возможность найти и сравнить. Поэтому товаров может быть не много, а очень много. Впрочем, я не думаю, что существует какая-то принципиальная разница между генерацией скрипта и использованием уже готового. Компы сейчас быстрые, а в производительности участвует так много факторов, что разница между этими двумя подходами незначительна.
Life is very short and there's no time
for fussing and fighting... (C) Paul McCartney & John Lennon
J_K>Речь идет о товарах, но не в магазине — сервис вроде поисковой системы. Мы сами ничего не продаем, а только предоставляем возможность найти и сравнить. Поэтому товаров может быть не много, а очень много. Впрочем, я не думаю, что существует какая-то принципиальная разница между генерацией скрипта и использованием уже готового. Компы сейчас быстрые, а в производительности участвует так много факторов, что разница между этими двумя подходами незначительна.
В таком случае можно поизобретать велосипеды например ввести понятие хэш кода расчитывающегося на основании полей и делать выборку в два этапа — сначала на стороне сервера вычисляем хэш код фильтруем по нему а уже в пределах найденного уточняем поиск или взять готовый велосипед на базе MapReduce (например Aster nCluster или Hadoop).
Хотя опять же, что значит очень много... на нескольких миллионах БД по прежнему вполне шустро выполняет запросы.
Возможно я не прав, но у меня сложилось впечатление, что ты пытаешься решить проблему , которая еще не возникла, оптимизировать стоит уже написанные запросы если они тормозят, а не пытаться изначально усложнить систему с целью повысить быстродействие. Ботлнек может оказаться совсем не на стороне базы.
L>Не поможет. Можно хоть обвешаться индексами, но если оптимизатор построил план, в котором используется индекс по полю A, а фактически ты ищешь по B, то индекс не поможет.
Oracle и MSSQL можно пнуть в запросе на прямое использование индексов.
Здравствуйте, VGn, Вы писали:
L>>Не поможет. Можно хоть обвешаться индексами, но если оптимизатор построил план, в котором используется индекс по полю A, а фактически ты ищешь по B, то индекс не поможет.
VGn>Oracle и MSSQL можно пнуть в запросе на прямое использование индексов.
Ну покажи, как в запросе пнуть на использование индекса в зависимости от значения параметра.
L>>>Не поможет. Можно хоть обвешаться индексами, но если оптимизатор построил план, в котором используется индекс по полю A, а фактически ты ищешь по B, то индекс не поможет.
VGn>>Oracle и MSSQL можно пнуть в запросе на прямое использование индексов.
L>Ну покажи, как в запросе пнуть на использование индекса в зависимости от значения параметра.
А причём тут значение параметра? Вопрос ставился: параметр A vs параметр B.
L>Здорово, что ты умеешь пользоваться гуглом. L>Но проблема не в отсутствии возможности указать оптимизатору какой индекс использовать, а в том, что план жостко привязан к тексту запросу. И если в плане стоит использование индекса по A, а параметры запроса таковы, что искать нужно не по A, а по B, то хоть тресни, а не заставишь сервер искать по B.
А вот ты наверное не умеешь даже читать по ссылкам. Хинтование управляет построением плана запроса.
L>>>Ну покажи, как в запросе пнуть на использование индекса в зависимости от значения параметра.
VGn>>А причём тут значение параметра? Вопрос ставился: параметр A vs параметр B.
L>Такой вопрос не ставился. Прочитай ветку полностью до корня.
Ничего кроме вопроса наличия ограничений я не нашёл.
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, ты делаешь условие на В.
А если на А, то, соответственно, — на А.
И в запросе уже описано, что ты хочешь. А значит такой запрос можно с большой вероятностью тюнинговать так, чтобы и база поняла, что ты хочешь. И тогда всё будет работать максимально быстро.
Но на гибких системах это трудно. Думаю, это даже искусство.
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, т.е. в любом случае будет сочетание параметров, для которого выбраный план не лучший.
Безусловно. Но во-первых идеала нет, а во-вторых индексы всё-равно будут использоваться.
Здравствуйте, 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>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.