![]() |
|
Модераторы: LSD, AntonSaburov |
![]()
|
|
| boroda |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 2.12.2005 Где: Киев Репутация: 1 Всего: 1 |
Добрый день.
Есть сторед процедура в MySQL DROP PROCEDURE IF EXISTS `test`.`b_insert` $$ CREATE PROCEDURE `test`.`b_insert` (IN aName TEXT, IN aCountry TEXT) BEGIN DECLARE country TEXT; call b_getCountryID(@countryID,aCountry); set country=@countryID; insert into testTable(name, idCoutry) values(aName, country); END $$ DELIMITER ; Когда я ее вызываю процедуру b_insert из какого-либо клиента MySQL(MySQL Command Line Client, MySQL Query Browser), то внутрення процедура b_getCountryID возвращает нужное значение. Если же я вызываю b_insert из сервела то процедура b_getCountryID возвращает NULL. Где собака порылась? Или как можно решить данную проблему? Заранее спасибо |
|||
|
||||
| 3x3 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 261 Регистрация: 17.9.2006 Репутация: 5 Всего: 8 |
Видимо, если у вас b_getCountryID возвращает неправильное значение, то надо на неё и смотреть, а не на b_insert. К тому же, вопрос, видимо в компетенции не этого, а вот этого форума.. -------------------- Зачем платить больше, когда можно заплатить дважды? |
|||
|
||||
| boroda |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 2.12.2005 Где: Киев Репутация: 1 Всего: 1 |
Как раз вопроса к MySQL у меня нет процедура b_getCountryID возвращает нужное значение (Поэтому считаю что мой вопрос в компетенции все-таки этого форума). Просто когда вызываю b_insert из java сервлета то b_getCountryID возвращает NULL. Но всеравно спасибо |
|||
|
||||
| 3x3 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 261 Регистрация: 17.9.2006 Репутация: 5 Всего: 8 |
Не за что.
Вот вам система из двух уравнений: 1. процедура b_getCountryID возвращает нужное значение. 2. из java сервлета b_getCountryID возвращает NULL. Вывод из приведенной совокупности ваших утверждений только один: NULL - это нужное значение. Хотя что-то подсказывает мне, что вас понимать следует таким образом, что b_getCountryID не всегда возвращает правильное значение, так? А если это так, то и разбираться нужно с ней, а не с той процедурой, которая её использует, согласитесь. -------------------- Зачем платить больше, когда можно заплатить дважды? |
|||
|
||||
| boroda |
|
||||
|
Новичок Профиль Группа: Участник Сообщений: 29 Регистрация: 2.12.2005 Где: Киев Репутация: 1 Всего: 1 |
Ну вывод не правильный так как процедура b_getCountryID у меня в принципе не может вернуть NULL. Понимать следует именно так как я написал еще впервом сообщении. Т.е. при абсолютно одинакових входящих параметрах если я пишу в MySQL Command Line Client к примеру call b_insert('Something','Russia'); Все работает отлично. В джава сервлете при вызове процедуры call b_insert('Something','Russia'). в таблицу testTable ничего не записывается по т.к. b_getCountryID возвращает NULL. Вот код процедуры b_getCountryID
а вот содержание таблицы country
P.S. Я конечно решил этот вопрос методом топора, т.е. в Java сервлете я изначально вызвал процедуру b_getCountryID, потом b_insert и в нее я передал то что вернула мне b_getCountryID. Сейчас все работает, но при этом мне всеравно интересно в чем проблема? |
||||
|
|||||
| 3x3 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 261 Регистрация: 17.9.2006 Репутация: 5 Всего: 8 |
Я бы вам посоветовал рассмотреть вопрос о переходе с вызовов хранимых процедур на запросы вида:
Мало того, что это будет переносимое решение, но оно так же обычно оказывается лучше по производительности.. Что до NULL - он (а) всегда вставляется в testTable при вызове b_insert, (б) только при вызове b_insert из сервлета, но всегда, либо (в) произвольно? Если Я бы на вашем месте для начала попытался избавиться от @-переменной. -------------------- Зачем платить больше, когда можно заплатить дважды? |
|||
|
||||
| Sun |
|
|||
|
Account removed ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 1611 Регистрация: 14.8.2002 Репутация: 2 Всего: 48 |
А как может вызов запроса через JDBC быть более эффективным чем вызов вложенной процедуры, которая уже откомпилирована на сервере и следственно выполняется быстрее обычного запроса? -------------------- Account removed |
|||
|
||||
| 3x3 |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 261 Регистрация: 17.9.2006 Репутация: 5 Всего: 8 |
Кстати, а такая процедура не работает?
А такая вроде бы вообще должна возвращать значение подобно функции:
Но лучше для этой конкретной цели использовать все-таки SQL-выражение.. -------------------- Зачем платить больше, когда можно заплатить дважды? |
||||
|
|||||
| 3x3 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 261 Регистрация: 17.9.2006 Репутация: 5 Всего: 8 |
За MySQL не стану ручаться, но по аналогии с Oracle - запрос компилируется так же однократно, потом сидит в кеше. При этом, для данного типа запроса у него с большой вероятностью уже и данные в кеше готовые лежат, к справочнику-то часто обращаются, а вот процедуру всё равно придётся выполнить - оптимизатор не знает какова логика процедуры. Плюс небольшие затратах на вызов процедуры в т.ч. инициализацию пакета, проверку привелегий и т.д., она ведь исполняется с правами своего владельца. Но главное, при использовании обращения к справочнику по странам в качестве подзапроса, оптимизатор запросов, работая с запросом ( в д.с. INSERT, но сложный SELECT был бы лучшим примером), будет его как нетрудно догадаться, оптимизировать - исходя из статистики таблиц к которым обращается запрос, наличия индексов, способа связывания и т.п. Он будет выбирать по каким индексам каких участвующих таблиц осуществлять внешние циклы, а по каким внутренние, да и по индексам ли вообще это делать. Заменяя подзапросы вызовами хранимых процедур вы лишите оптимизатор возможности выбора стратегии. -------------------- Зачем платить больше, когда можно заплатить дважды? |
|||
|
||||
| batigoal |
|
|||
![]() Нелетучий Мыш ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6423 Регистрация: 28.12.2004 Где: Санктъ-Петербургъ Репутация: 16 Всего: 151 |
Не совсем. Это было бы справедливо, если бы мы использовали PreparedStatement, и биндили его переменные. Если же мы будем втупую "склеивать" запрос, то он будет заново парситься, составляться план и т.д. -------------------- "Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли) ЖоржЖЖ |
|||
|
||||
| ALKS |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 354 Регистрация: 22.3.2006 Репутация: 6 Всего: 11 |
Угу. А в случае с MSSQL с увереностью берусь утверждать, что преренос кода в хранимые процедуры практически всегда лучшее с точки зрения производительности решение. и заметно лучшее.
И еще одно хотелось бы заметить - борьба за переносимость SQL запросов между серверами баз данных, это вообще крайне порочное занятие изначально. п.с. простите искреен за офтоп. зацепило почему-то |
|||
|
||||
| 3x3 |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 261 Регистрация: 17.9.2006 Репутация: 5 Всего: 8 |
Не так. SQL-движок Oracle ничего не знает про JDBCшный PreparedStatement. Он получает select чего-то там через соединение, берет от него хеш и смотрит во внутренних структурах - а не завалялся ли там уже такой запрос и если нашел - берет адрес уже готовой структуры. Ну и с планом, вроде такая же фигня - во вью v$sql бывает можно встретить одинаковые запросы, с идентичными хешами, что меня заставляет думать, что они отличаются контекстом построения запроса (optimizer_env), но специально не интересовался, может и не по этому. Биндинг переменных - естественно, по умолчанию. Это и безопаснее всегда, и в случае с Oracle, запросы должны быть идентичны, что бы их хеши сошлись. -------------------- Зачем платить больше, когда можно заплатить дважды? |
||||
|
|||||
| 3x3 |
|
||||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 261 Регистрация: 17.9.2006 Репутация: 5 Всего: 8 |
Никогда в жизни не поверю, что вызов процедуры может ускорить запрос. Вот давайте возьмем табличку стран и табличку людей и попробуем вытащить имена всех австралийских мужчин:
Как должна отрабатывать база подобный запрос? Пойти перебирать людей сверяясь каждый раз с их страной и по ней с континентом, вызывая нужные функции? Но ведь у нас 7 миллиардов людей сосредоточено в 200 странах и худо-бедно индексы существуют, и их селективность известна оптимизатору. По этому он найдет единственную страну на континенте Австралия и вытащит ветку индекса таблицы персон, содержащую указатели на персоны там живущие, и будет выбирать с диска блоки данных, содержащие только эти персоны, а не лопатить миллиарды записей персон. Ситуация может быть и иная - может не быть некоторых индексов, данные могут лежать очень разреженно, у вас в базе может быть не 7 миллиардов людей, а 300 сотрудников из этих 200 стран - в каждом случае оптимизатор выберет наиболее выигрышную стратегию - как с наименьшими затратами выбрать для вас интересующий набор данных. И MySQL не может быть исключением. Он же тоже из каких-то соображений строит план запроса, использует те или иные индексы? Но как только вы начинаете пользоваться функциями - всё, оптимизация идёт лесом.
Но нет смысла городить сложности на пустом месте. В специальных случаях, когда не работает общее решение - никто не мешает его оговорить особо - перерекрыть общий случай, работающий везде своими настройками, подогнанными под частный случай. Так и надо разрабатывать софт, ведь дело не только в переносимости между RDBMS, дело в переносимости продукта между разными клиентами, сидящими под одной и той же версией RDBMS. У всех разные "обстоятельства" в базе и продукт должен быть готов быть немного подкручен под конкретный случай. Под одним заказчиком сидеть прикажете? Так он вас же и купит в итоге
Теперь оправдываться поздно. Посмотри на это небо, эти звёзды.. -------------------- Зачем платить больше, когда можно заплатить дважды? |
||||||||
|
|||||||||
| batigoal |
|
|||
![]() Нелетучий Мыш ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 6423 Регистрация: 28.12.2004 Где: Санктъ-Петербургъ Репутация: 16 Всего: 151 |
-------------------- "Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли) ЖоржЖЖ |
|||
|
||||
| 3x3 |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 261 Регистрация: 17.9.2006 Репутация: 5 Всего: 8 |
1. PreparedStatement ни при чем 2. Случай с параметрами, вписанными внутрь запроса просто не рассматривается А в остальном - всё так, конечно -------------------- Зачем платить больше, когда можно заплатить дважды? |
|||
|
||||
![]()
|
| Правила форума "Java" | |
|
|
Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |