Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема с вызовом внутренней процедуры в MySQL 
:(
    Опции темы
boroda
Дата 27.9.2006, 11:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 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. Где собака порылась? Или как можно решить данную проблему?

Заранее спасибо
PM MAIL   Вверх
3x3
Дата 28.9.2006, 15:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 261
Регистрация: 17.9.2006

Репутация: 5
Всего: 8



Цитата(boroda @ 27.9.2006,  11:30)
внутрення процедура b_getCountryID возвращает нужное значение. Если же я вызываю b_insert из сервела то процедура b_getCountryID возвращает NULL.

Видимо, если у вас b_getCountryID возвращает неправильное значение, то надо на неё и смотреть, а не на b_insert.

К тому же, вопрос, видимо в компетенции не этого, а вот этого форума..


--------------------
Зачем платить больше,
когда можно заплатить дважды?
PM   Вверх
boroda
Дата 28.9.2006, 18:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 2.12.2005
Где: Киев

Репутация: 1
Всего: 1



Цитата(boroda @ 27.9.2006,  11:30)
 Когда я ее вызываю процедуру b_insert из какого-либо клиента MySQL(MySQL Command Line Client, MySQL Query Browser), то внутрення процедура b_getCountryID возвращает нужное значение. Если же я вызываю b_insert из сервела то процедура b_getCountryID возвращает NULL. 


Как раз вопроса к MySQL у меня нет процедура b_getCountryID возвращает нужное значение (Поэтому считаю что мой вопрос в компетенции все-таки этого форума). Просто когда вызываю b_insert из java сервлета то b_getCountryID возвращает NULL.


Но всеравно спасибо


PM MAIL   Вверх
3x3
  Дата 29.9.2006, 00:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 261
Регистрация: 17.9.2006

Репутация: 5
Всего: 8



Не за что. 

Вот вам система из двух уравнений:

1. процедура b_getCountryID возвращает нужное значение.
2. из java сервлета b_getCountryID возвращает NULL.

Вывод из приведенной совокупности ваших утверждений только один: NULL - это нужное значение. 

Хотя что-то подсказывает мне, что вас понимать следует таким образом, что b_getCountryID не всегда возвращает правильное значение, так? А если это так, то и разбираться нужно с ней, а не с той процедурой, которая её использует, согласитесь. 







--------------------
Зачем платить больше,
когда можно заплатить дважды?
PM   Вверх
boroda
Дата 29.9.2006, 12:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 2.12.2005
Где: Киев

Репутация: 1
Всего: 1



smile) 
Ну вывод не правильный так как процедура b_getCountryID у меня в принципе не может вернуть NULL. Понимать следует именно так как я написал еще впервом сообщении. Т.е. при абсолютно одинакових  входящих параметрах если я пишу в MySQL Command Line Client к примеру call b_insert('Something','Russia'); Все работает отлично. В джава сервлете при вызове процедуры call b_insert('Something','Russia'). в таблицу testTable ничего не записывается по т.к. b_getCountryID возвращает NULL.

Вот код процедуры b_getCountryID
Код

DELIMITER $$

DROP PROCEDURE IF EXISTS `matco`.`b_getCountryID` $$
CREATE PROCEDURE `b_getCountryID`(OUT rows TEXT, IN aName TEXT)
BEGIN
 DECLARE done INT DEFAULT 0;
 DECLARE vIdCountry TEXT;
 DECLARE curIdCountry CURSOR FOR
   SELECT idCountry FROM country where name=aName;
 DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1;

   OPEN curIdCountry;
   REPEAT
     FETCH curIdCountry INTO vIdCountry;
      IF NOT done THEN
       SET rows = vIdCountry;
      END IF;
   UNTIL done END REPEAT;
   CLOSE curIdCountry;

END $$

DELIMITER ;


а вот содержание таблицы country 
Код

+-----------+-------------+
| idCountry | Name        |
+-----------+-------------+
|         1 | Russia      |
|         2 | Switzerland |
+-----------+-------------+


P.S. Я конечно решил этот вопрос методом топора, т.е. в Java сервлете я изначально вызвал процедуру  b_getCountryID, потом b_insert и в нее я передал то что вернула мне b_getCountryID. Сейчас все работает, но при этом мне всеравно интересно в чем проблема?
PM MAIL   Вверх
3x3
Дата 29.9.2006, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 261
Регистрация: 17.9.2006

Репутация: 5
Всего: 8



Я бы вам посоветовал рассмотреть вопрос о переходе с вызовов хранимых процедур на запросы вида:
Код

insert into testTable(name, idCoutry)  select 'lalala' /* it is your aName parameter */ ,idCountry from country where name='Russia' /* it is your aCountry */;

Мало того, что это будет переносимое решение, но оно так же обычно оказывается лучше по производительности..

Что до NULL - он (а) всегда вставляется в testTable при вызове b_insert, (б) только при вызове b_insert из сервлета, но всегда, либо (в) произвольно?

Если Я бы на вашем месте для начала попытался избавиться от @-переменной.


--------------------
Зачем платить больше,
когда можно заплатить дважды?
PM   Вверх
Sun
Дата 29.9.2006, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



Цитата(3x3 @  29.9.2006,  13:15 Найти цитируемый пост)
Мало того, что это будет переносимое решение, но оно так же обычно оказывается лучше по производительности.

А как может вызов запроса через JDBC быть более эффективным чем вызов вложенной процедуры, которая уже откомпилирована на сервере и следственно выполняется быстрее обычного запроса?


--------------------
Account removed
PM MAIL   Вверх
3x3
Дата 29.9.2006, 16:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 261
Регистрация: 17.9.2006

Репутация: 5
Всего: 8



Кстати, а такая процедура не работает?

Код

CREATE PROCEDURE b_getCountryID(OUT rows TEXT, IN aName TEXT)
BEGIN
   SELECT idCountry INTO rows FROM country where name=aName;
END;


А такая вроде бы вообще должна возвращать значение подобно функции:
Код

CREATE PROCEDURE b_getCountryID(IN aName TEXT)
BEGIN
   SELECT idCountry FROM country where name=aName;
END;


Но лучше для этой конкретной цели использовать все-таки SQL-выражение..


--------------------
Зачем платить больше,
когда можно заплатить дважды?
PM   Вверх
3x3
Дата 29.9.2006, 17:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 261
Регистрация: 17.9.2006

Репутация: 5
Всего: 8



Цитата(Sun @ 29.9.2006,  16:35)
Цитата(3x3 @  29.9.2006,  13:15 Найти цитируемый пост)
Мало того, что это будет переносимое решение, но оно так же обычно оказывается лучше по производительности.

А как может вызов запроса через JDBC быть более эффективным чем вызов вложенной процедуры, которая уже откомпилирована на сервере и следственно выполняется быстрее обычного запроса?

За MySQL не стану ручаться, но по аналогии с Oracle - запрос компилируется так же однократно, потом сидит в кеше. При этом, для данного типа запроса у него с большой вероятностью уже и данные в кеше готовые лежат, к справочнику-то часто обращаются, а вот процедуру всё равно придётся выполнить - оптимизатор не знает какова логика процедуры.
Плюс небольшие затратах на вызов процедуры в т.ч. инициализацию пакета, проверку привелегий и т.д., она ведь исполняется с правами своего владельца. 
Но главное, при использовании обращения к справочнику по странам в качестве подзапроса, оптимизатор запросов, работая с запросом ( в д.с. INSERT, но сложный SELECT был бы лучшим примером), будет его как нетрудно догадаться, оптимизировать - исходя из статистики таблиц к которым обращается запрос, наличия индексов, способа связывания и т.п. Он будет выбирать по каким индексам каких участвующих таблиц осуществлять внешние циклы, а по каким внутренние, да и по индексам ли вообще это делать. Заменяя подзапросы вызовами хранимых процедур вы лишите оптимизатор возможности выбора стратегии. 


--------------------
Зачем платить больше,
когда можно заплатить дважды?
PM   Вверх
batigoal
Дата 1.10.2006, 20:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нелетучий Мыш
****


Профиль
Группа: Участник Клуба
Сообщений: 6423
Регистрация: 28.12.2004
Где: Санктъ-Петербургъ

Репутация: 16
Всего: 151



Цитата(3x3 @  29.9.2006,  18:08 Найти цитируемый пост)
но по аналогии с Oracle - запрос компилируется так же однократно, потом сидит в кеше

Не совсем. Это было бы справедливо, если бы мы использовали PreparedStatement, и биндили его переменные. Если же мы будем втупую "склеивать" запрос, то он будет заново парситься, составляться план и т.д.


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли)
ЖоржЖЖ
PM WWW   Вверх
ALKS
Дата 1.10.2006, 21:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 354
Регистрация: 22.3.2006

Репутация: 6
Всего: 11



Угу. А в случае с MSSQL с увереностью берусь утверждать, что преренос кода в хранимые процедуры практически всегда лучшее с точки зрения производительности решение. и заметно лучшее.

И еще одно хотелось бы заметить - борьба за переносимость SQL запросов между серверами баз данных, это вообще крайне порочное занятие изначально. 

п.с. простите искреен за офтоп. зацепило почему-то smile
PM   Вверх
3x3
Дата 1.10.2006, 22:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 261
Регистрация: 17.9.2006

Репутация: 5
Всего: 8



Цитата(batigoal @ 1.10.2006,  20:06)
Цитата(3x3 @  29.9.2006,  18:08 Найти цитируемый пост)
но по аналогии с Oracle - запрос компилируется так же однократно, потом сидит в кеше

Не совсем. Это было бы справедливо, если бы мы использовали PreparedStatement, и биндили его переменные. Если же мы будем втупую "склеивать" запрос, то он будет заново парситься, составляться план и т.д.

Не так. SQL-движок Oracle ничего не знает про JDBCшный PreparedStatement. Он получает select чего-то там через соединение, берет от него хеш и смотрит во внутренних структурах - а не завалялся ли там уже такой запрос и если нашел - берет адрес уже готовой структуры. Ну и с планом, вроде такая же фигня - во вью v$sql бывает можно встретить одинаковые запросы, с идентичными хешами, что меня заставляет думать, что они отличаются контекстом построения запроса (optimizer_env), но специально не интересовался, может и не по этому.

Биндинг переменных - естественно, по умолчанию. Это и безопаснее всегда, и в случае с Oracle, запросы должны быть идентичны, что бы их хеши сошлись.


--------------------
Зачем платить больше,
когда можно заплатить дважды?
PM   Вверх
3x3
Дата 1.10.2006, 23:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 261
Регистрация: 17.9.2006

Репутация: 5
Всего: 8



Цитата(ALKS @ 1.10.2006,  21:05)
Угу. А в случае с MSSQL с увереностью берусь утверждать, что преренос кода в хранимые процедуры практически всегда лучшее с точки зрения производительности решение. и заметно лучшее.


Никогда в жизни не поверю, что вызов процедуры может ускорить запрос.
Вот давайте возьмем табличку стран и табличку людей и попробуем вытащить имена всех австралийских мужчин:

Код

SELECT person.id, person.name FROM person, country, continent WHERE country.id=person.country_id AND person.sex='M' AND country.continent_id=continent.id AND continent.name='Australia';


Как должна отрабатывать база подобный запрос? Пойти перебирать людей сверяясь каждый раз с их страной и по ней с континентом, вызывая нужные функции?

Но ведь у нас 7 миллиардов людей сосредоточено в 200 странах и худо-бедно индексы существуют, и их селективность известна оптимизатору. По этому он найдет единственную страну на континенте Австралия и вытащит ветку индекса таблицы персон, содержащую указатели на персоны там живущие, и будет выбирать с диска блоки данных, содержащие только эти персоны, а не лопатить миллиарды записей персон.

Ситуация может быть и иная - может не быть некоторых индексов, данные могут лежать очень разреженно, у вас в базе может быть не 7 миллиардов людей, а 300 сотрудников из этих 200 стран - в каждом случае оптимизатор выберет наиболее выигрышную стратегию - как с наименьшими затратами выбрать для вас интересующий набор данных. 

И MySQL не может быть исключением. Он же тоже из каких-то соображений строит план запроса, использует те или иные индексы? Но как только вы начинаете пользоваться функциями - всё, оптимизация идёт лесом. 


Цитата

И еще одно хотелось бы заметить - борьба за переносимость SQL запросов между серверами баз данных, это вообще крайне порочное занятие изначально. 

Но нет смысла городить сложности на пустом месте. В специальных случаях, когда не работает общее решение - никто не мешает его оговорить особо -  перерекрыть общий случай, работающий везде своими настройками, подогнанными под частный случай. Так и надо разрабатывать софт, ведь дело не только в переносимости между RDBMS, дело в переносимости продукта между разными клиентами, сидящими под одной и той же версией RDBMS. У всех разные "обстоятельства" в базе и продукт должен быть готов быть немного подкручен под конкретный случай. Под одним заказчиком сидеть прикажете? Так он вас же и купит в итоге smile


Цитата

п.с. простите искреен за офтоп. зацепило почему-то smile

Теперь оправдываться поздно. Посмотри на это небо, эти звёзды..


--------------------
Зачем платить больше,
когда можно заплатить дважды?
PM   Вверх
batigoal
Дата 2.10.2006, 08:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нелетучий Мыш
****


Профиль
Группа: Участник Клуба
Сообщений: 6423
Регистрация: 28.12.2004
Где: Санктъ-Петербургъ

Репутация: 16
Всего: 151



Цитата(3x3 @  1.10.2006,  23:54 Найти цитируемый пост)
Не так.

Ээээ... А в чем же тут противоречие с моими словами?


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли)
ЖоржЖЖ
PM WWW   Вверх
3x3
Дата 2.10.2006, 11:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 261
Регистрация: 17.9.2006

Репутация: 5
Всего: 8



Цитата(batigoal @ 2.10.2006,  08:36)
Цитата(3x3 @  1.10.2006,  23:54 Найти цитируемый пост)
Не так.

Ээээ... А в чем же тут противоречие с моими словами?

1. PreparedStatement ни при чем
2. Случай с параметрами, вписанными внутрь запроса просто не рассматривается

А в остальном - всё так, конечно smile


--------------------
Зачем платить больше,
когда можно заплатить дважды?
PM   Вверх
batigoal
Дата 2.10.2006, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нелетучий Мыш
****


Профиль
Группа: Участник Клуба
Сообщений: 6423
Регистрация: 28.12.2004
Где: Санктъ-Петербургъ

Репутация: 16
Всего: 151



Не понял я твою мысль, ну да ладно. Не существенно.


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли)
ЖоржЖЖ
PM WWW   Вверх
Sun
Дата 2.10.2006, 14:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



Цитата(3x3 @  1.10.2006,  20:35 Найти цитируемый пост)
Никогда в жизни не поверю, что вызов процедуры может ускорить запрос.

А у меня гораздо больше сомнений вызывает что переданный извне запрос будет выполняться быстрей чем в теле процедуры. Допускаю что в лучшем случае скорость будет одинаковой. У вас есть какие-нибудь материалы доказывающие вашу теорию? Интересно было бы почитать.


--------------------
Account removed
PM MAIL   Вверх
3x3
  Дата 2.10.2006, 15:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 261
Регистрация: 17.9.2006

Репутация: 5
Всего: 8



Цитата(Sun @ 2.10.2006,  14:42)
Цитата(3x3 @  1.10.2006,  20:35 Найти цитируемый пост)
Никогда в жизни не поверю, что вызов процедуры может ускорить запрос.

А у меня гораздо больше сомнений вызывает что переданный извне запрос будет выполняться быстрей чем в теле процедуры. Допускаю что в лучшем случае скорость будет одинаковой. У вас есть какие-нибудь материалы доказывающие вашу теорию? Интересно было бы почитать.

А вы не обратили внимания, что в посте, из которого вы процитировали одну фразу, присутствует ещё некая совокупность букв, посвященная раскрытию темы - почему именно я не поверю?  smile 

Это сообщение отредактировал(а) 3x3 - 2.10.2006, 15:10


--------------------
Зачем платить больше,
когда можно заплатить дважды?
PM   Вверх
Sun
Дата 2.10.2006, 15:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



Цитата(3x3 @  2.10.2006,  12:08 Найти цитируемый пост)
А вы не обратили внимания, что в посте, из которого вы процитировали одну фразу, присутствует ещё некая совокупность букв, посвященная раскрытию темы - почему именно я не поверю? 

Я внимательнейшим образом изучил данный метериал, но так и не понял почему если оптимизатор запускается при простом выполнении запроса, он точно также не запускается при выполнении этого же запроса в теле процедуры? Это сделано специально чтобы понизить эффективность хранимых процедур?


--------------------
Account removed
PM MAIL   Вверх
3x3
Дата 2.10.2006, 16:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 261
Регистрация: 17.9.2006

Репутация: 5
Всего: 8



Цитата(Sun @ 2.10.2006,  15:28)
Цитата(3x3 @  2.10.2006,  12:08 Найти цитируемый пост)
А вы не обратили внимания, что в посте, из которого вы процитировали одну фразу, присутствует ещё некая совокупность букв, посвященная раскрытию темы - почему именно я не поверю? 

Я внимательнейшим образом изучил данный метериал, но так и не понял почему если оптимизатор запускается при простом выполнении запроса, он точно также не запускается при выполнении этого же запроса в теле процедуры? Это сделано специально чтобы понизить эффективность хранимых процедур?

Хм.. Я в свою очередь не понимаю, как вы себе представляете работу оптимизатора в случае, если запрос, приведенный мною в качестве примера, будет подбирать ID стран и континентов посредством вызова функций:
Код

SELECT person.id, person.name FROM person WHERE country.id=get_country_id(get_continent_id('Australia')) AND person.sex='M';


Как вы ему предложите ЭТО оптимизировать? Он просто станет вызывать эти функции для всех семи миллиардов землян и шерстить в них страны и континенты. 


--------------------
Зачем платить больше,
когда можно заплатить дважды?
PM   Вверх
Sun
Дата 2.10.2006, 17:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



Цитата(3x3 @  2.10.2006,  13:35 Найти цитируемый пост)
Как вы ему предложите ЭТО оптимизировать? Он просто станет вызывать эти функции для всех семи миллиардов землян и шерстить в них страны и континенты.  

Ну в процедурах есть параметры, которые я укажу в данном селекте. Соотвественно когда будет выполняться селект с указанными параметрами, будет вызываться и оптимизатор, точно также как и при вызове запроса извне. Разве не так? Или я что-то недопонял?


--------------------
Account removed
PM MAIL   Вверх
3x3
Дата 2.10.2006, 18:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 261
Регистрация: 17.9.2006

Репутация: 5
Всего: 8



Цитата(Sun @ 2.10.2006,  17:02)
Цитата(3x3 @  2.10.2006,  13:35 Найти цитируемый пост)
Как вы ему предложите ЭТО оптимизировать? Он просто станет вызывать эти функции для всех семи миллиардов землян и шерстить в них страны и континенты.  

Ну в процедурах есть параметры, которые я укажу в данном селекте. Соотвественно когда будет выполняться селект с указанными параметрами, будет вызываться и оптимизатор, точно также как и при вызове запроса извне. Разве не так? Или я что-то недопонял?

Продолжая наш пример:
В мире живёт примерно 7 миллиардов человек (ну, миллиард туда, миллиард сюда - не принципиально).
Население Австралии - что-то около 20 миллионов, что составляет 0.3% от общего количества людей.

В среднем же селективность индекса по странам, которых 200 = 0.5%, очень хорошая избирательность, проиндексируем персон по стране.

Соответственно оптимизатор знает какие существуют индексы (в жизни он ещё оценивает и сколько стоит по ним ходить, ведь данные разреживаются с годами: кто-то мрёт, кто-то наоборот).

И когда мы просим SQL-engine: "дай нам всех мужиков с австралийского континента" она в состоянии решить что правильнее: перебирать семь миллиардов записей персон или 6 континентов, 34 страны (в среднем на континент) и двадцать миллионов персон.

Но стоит вам сказать SQL-engine: "дай нам всех мужиков, у которых ID страны, совпадёт с ID, которой вернет фукция вызванная для этой записи" - и всё. БД пойдёт перебирать миллиарды землян и для каждого вызывать функцию и проверять - совпадает ли возвращенный ID с тем, что забито в записи этого пользователя. 

ЗЫ
Не без исключений, конечно. В частности при выборке по Азии будет скорее всего выгоднее ходить по персонам: одних китайцев - каждый пятый, какой блок с диска ни считаешь - не ошибёшься, в нём уже китаец сидеть будет smile



--------------------
Зачем платить больше,
когда можно заплатить дважды?
PM   Вверх
Sun
Дата 2.10.2006, 19:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



Цитата(3x3 @  2.10.2006,  15:00 Найти цитируемый пост)
И когда мы просим SQL-engine: "дай нам всех мужиков с австралийского континента" она в состоянии решить что правильнее: перебирать семь миллиардов записей персон или 6 континентов, 34 страны (в среднем на континент) и двадцать миллионов персон.

Можно все-таки пример на SQL, а то с такими яыком запросов который приводите вы я не знаком  smile  А еще лучше Java код с вызовом SQL и код хранимой процедуры которая по вашему мнению отработает медленней. Пока что в вашем примере я не вижу конкретики. Его можно эффективно реализовать и через хранимые процедуры и через JDBC вызовы.


--------------------
Account removed
PM MAIL   Вверх
3x3
  Дата 2.10.2006, 19:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 261
Регистрация: 17.9.2006

Репутация: 5
Всего: 8



Цитата(Sun @ 2.10.2006,  19:42)
Цитата(3x3 @  2.10.2006,  15:00 Найти цитируемый пост)
И когда мы просим SQL-engine: "дай нам всех мужиков с австралийского континента" она в состоянии решить что правильнее: перебирать семь миллиардов записей персон или 6 континентов, 34 страны (в среднем на континент) и двадцать миллионов персон.

Можно все-таки пример на SQL, а то с такими яыком запросов который приводите вы я не знаком  smile  А еще лучше Java код с вызовом SQL и код хранимой процедуры которая по вашему мнению отработает медленней. Пока что в вашем примере я не вижу конкретики. Его можно эффективно реализовать и через хранимые процедуры и через JDBC вызовы.

На SQL было в предшествующих постах, а это перевод выражения на русский язык smile

А про джаву - забудьте. Совершенно непринципиально через какой API вы будете дергать лисэнер БД. Это базу не волнует и на её скорость не влияет.


--------------------
Зачем платить больше,
когда можно заплатить дважды?
PM   Вверх
Sun
Дата 2.10.2006, 20:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



Цитата(3x3 @  2.10.2006,  16:59 Найти цитируемый пост)
А про джаву - забудьте. Совершенно непринципиально через какой API вы будете дергать лисэнер БД. Это базу не волнует и на её скорость не влияет. 

Ладно, будем абстрагироваться. У нас есть один и тотже SQL запрос со следующими параметрами
Код

SELECT person.id, person.name FROM person, country, continent WHERE country.id=person.country_id AND person.sex='M' AND country.continent_id=continent.id AND continent.name='Australia';

В одном случае мы вызываем его в теле хранимой процедуры, во втором извне, через API предоставляемое сервером баз данных, либо через поставляемую вместе с ним утилиту. Теперь можно узнать - почему при запуске SQL запроса из хранимой процедуры оптимизатор запускаться не будет, а во втором случае будет? 


--------------------
Account removed
PM MAIL   Вверх
3x3
Дата 2.10.2006, 20:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 261
Регистрация: 17.9.2006

Репутация: 5
Всего: 8



1. Оптимизатор будет вызываться всегда, какой бы вы ему запрос не скормили (оставим за скобками оракловые особенности)
2. Разницы в том, как будет выполняться целый запрос: из хранимой процедуры или из вью или из клиента пришедши - естественно, практически нет.


--------------------
Зачем платить больше,
когда можно заплатить дважды?
PM   Вверх
Sun
Дата 2.10.2006, 20:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



3x3, ну если разницы нет, почему же вы утверждаете что хранимые процедуры менее эффективны по производительности, чем внешние вызовы? Только потому что требуется проверка прав доступа? Время на инициализацию?


--------------------
Account removed
PM MAIL   Вверх
3x3
Дата 2.10.2006, 20:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 261
Регистрация: 17.9.2006

Репутация: 5
Всего: 8



Цитата(Sun @ 2.10.2006,  20:45)
3x3, ну если разницы нет, почему же вы утверждаете что хранимые процедуры менее эффективны по производительности, чем внешние вызовы? Только потому что требуется проверка прав доступа? Время на инициализацию?

Это вы так интерпретировали моё высказывание: "Никогда в жизни не поверю, что вызов процедуры может ускорить запрос" или можете привести ссылку на высказывание о том, "что хранимые процедуры менее эффективны по производительности, чем внешние вызовы"? smile





--------------------
Зачем платить больше,
когда можно заплатить дважды?
PM   Вверх
Sun
Дата 2.10.2006, 21:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



Цитата(3x3 @  2.10.2006,  17:54 Найти цитируемый пост)
Это вы так интерпретировали моё высказывание: "Никогда в жизни не поверю, что вызов процедуры может ускорить запрос" или можете привести ссылку на высказывание о том, "что хранимые процедуры менее эффективны по производительности, чем внешние вызовы"? smile

Запросто
Цитата(3x3 @  29.9.2006,  13:15 Найти цитируемый пост)
Я бы вам посоветовал рассмотреть вопрос о переходе с вызовов хранимых процедур на запросы вида:
Код

insert into testTable(name, idCoutry)  select 'lalala' /* it is your aName parameter */ ,idCountry from country where name='Russia' /* it is your aCountry */;

Мало того, что это будет переносимое решение, но оно так же обычно оказывается лучше по производительности..


Цитата(3x3 @  29.9.2006,  14:08 Найти цитируемый пост)
Но главное, при использовании обращения к справочнику по странам в качестве подзапроса, оптимизатор запросов, работая с запросом ( в д.с. INSERT, но сложный SELECT был бы лучшим примером), будет его как нетрудно догадаться, оптимизировать - исходя из статистики таблиц к которым обращается запрос, наличия индексов, способа связывания и т.п. Он будет выбирать по каким индексам каких участвующих таблиц осуществлять внешние циклы, а по каким внутренние, да и по индексам ли вообще это делать. Заменяя подзапросы вызовами хранимых процедур вы лишите оптимизатор возможности выбора стратегии.  




--------------------
Account removed
PM MAIL   Вверх
3x3
Дата 2.10.2006, 21:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 261
Регистрация: 17.9.2006

Репутация: 5
Всего: 8



Цитата(Sun @ 2.10.2006,  21:05)
Цитата(3x3 @  2.10.2006,  17:54 Найти цитируемый пост)
Это вы так интерпретировали моё высказывание: "Никогда в жизни не поверю, что вызов процедуры может ускорить запрос" или можете привести ссылку на высказывание о том, "что хранимые процедуры менее эффективны по производительности, чем внешние вызовы"? smile

Запросто
Цитата(3x3 @  29.9.2006,  13:15 Найти цитируемый пост)
Я бы вам посоветовал рассмотреть вопрос о переходе с вызовов хранимых процедур на запросы вида:
Код

insert into testTable(name, idCoutry)  select 'lalala' /* it is your aName parameter */ ,idCountry from country where name='Russia' /* it is your aCountry */;

Мало того, что это будет переносимое решение, но оно так же обычно оказывается лучше по производительности..


Цитата(3x3 @  29.9.2006,  14:08 Найти цитируемый пост)
Но главное, при использовании обращения к справочнику по странам в качестве подзапроса, оптимизатор запросов, работая с запросом ( в д.с. INSERT, но сложный SELECT был бы лучшим примером), будет его как нетрудно догадаться, оптимизировать - исходя из статистики таблиц к которым обращается запрос, наличия индексов, способа связывания и т.п. Он будет выбирать по каким индексам каких участвующих таблиц осуществлять внешние циклы, а по каким внутренние, да и по индексам ли вообще это делать. Заменяя подзапросы вызовами хранимых процедур вы лишите оптимизатор возможности выбора стратегии.  

Хорошо. Я по-прежнему не вижу ссылку на высказывание о том, "что хранимые процедуры менее эффективны по производительности, чем внешние вызовы" (и уверен, что такого не говорил, поскольку не понимаю смысл текста взятого в кавычки), а вот отквоченное вами можно обсудить. 

Начнём.

С чем из отквоченного вами вы лично не согласны и почему?


--------------------
Зачем платить больше,
когда можно заплатить дважды?
PM   Вверх
Sun
Дата 2.10.2006, 21:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



boroda, привел текст процедуры в котором был следующий вызов
Код

insert into testTable(name, idCoutry) values(aName, country);

В приведенной мной цитате вы советуете заменить вызовы хранимых процедур прямым вызовом SQL запроса. Следуя из контекста темы, запрос должен вызываться из Java кода, то есть извне. Далее следует фраза "Мало того, что это будет переносимое решение, но оно так же обычно оказывается лучше по производительности" из чего я делаю логический вывод что вы считаете хранимые процедуры менее эффективными чем вызовы внешних SQL запросов.

Дальше по моей просьбе вы приводите доказательство своей мысли. Я ставлю его под сомнение, так как мне непонятно почему "Заменяя подзапросы вызовами хранимых процедур вы лишите оптимизатор возможности выбора стратегии.". Дальше мы приходим к выводу что вызов SQL запроса происходит практически одинаково как из хранимой процедуры, так и из внешнего приложения. На основе этого я делаю утверждение, что вы признали, что внешние SQL запросы не могут быть лучшими по производительности, чем хранимые процедуры  smile 


--------------------
Account removed
PM MAIL   Вверх
3x3
Дата 2.10.2006, 22:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 261
Регистрация: 17.9.2006

Репутация: 5
Всего: 8



Цитата(Sun @ 2.10.2006,  21:33)
boroda, привел текст процедуры в котором был следующий вызов
Код

insert into testTable(name, idCoutry) values(aName, country);

В приведенной мной цитате вы советуете заменить вызовы хранимых процедур прямым вызовом SQL запроса. 

Да, естественно. У процедур, конечно, есть своя роль в жини, но она не заключается в подмене частей обычных SQL-выражений. 


Цитата
Следуя из контекста темы, запрос должен вызываться из Java кода, то есть извне. 


Это может вытечь разве из соображений переносимости, вряд ли из контекста.

Цитата
Далее следует фраза "Мало того, что это будет переносимое решение, но оно так же обычно оказывается лучше по производительности" из чего я делаю логический вывод что вы считаете хранимые процедуры менее эффективными чем вызовы внешних SQL запросов.
Дальше по моей просьбе вы приводите доказательство своей мысли. Я ставлю его под сомнение, так как мне непонятно почему "Заменяя подзапросы вызовами хранимых процедур вы лишите оптимизатор возможности выбора стратегии.". Дальше мы приходим к выводу что вызов SQL запроса происходит практически одинаково как из хранимой процедуры, так и из внешнего приложения. На основе этого я делаю утверждение, что вы признали, что внешние SQL запросы не могут быть лучшими по производительности, чем хранимые процедуры  smile


Я начинаю вас понимать smile 
Вы немножко забываете о том, что кроме отработки вызова, серверу ещё нужно сделать некоторую полезную работу.
Я не думаю, что вы мне приведёте пример базы данных, в которой времени на отработку собственно вызов тратится больше, чем на работу - такая система просто не смогла бы работать постоянно с полной нагрузкой, периодически уходя в отказ в обслуживании при переполнении очереди вызовов, да в случаях когда время обращения к серверу критично - используются более другие решения: прямая загрузка данных в базу в обход ограничений целостности, кеширование огромных объемов данных на сервере приложений и т.п. 

PS
Кстати, с точки зрения сопровождения БД 24х7 будет любопытно взглянуть как вы в работающей базе будете при необходимости апдейтить две функции, из которых одна вызывает другую - ну мало ли что там поменялось ;)


PPS
А у вас аватар не просто так выбран? По SunOS можно обратиться с вопросиком?
 




Это сообщение отредактировал(а) 3x3 - 2.10.2006, 22:40


--------------------
Зачем платить больше,
когда можно заплатить дважды?
PM   Вверх
3x3
  Дата 3.10.2006, 03:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 261
Регистрация: 17.9.2006

Репутация: 5
Всего: 8



Вобщем, проверил на практике. Начерно, конечно, но меня устраивает smile 
А кому не нравятся мои результаты - могут опровергать своими, код приведен. 

База:
Код

CREATE TABLE `xcountry` (`c_id` int(11) NOT NULL,`c_name` varchar(200) NOT NULL,PRIMARY KEY  (`c_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `xtest` (`t_name` varchar(200) NOT NULL,`c_id` int(11) default NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE FUNCTION `xget_country_id`(aName varchar(200)) RETURNS int(11)                                  
  READS SQL DATA DETERMINISTIC                               
BEGIN
  DECLARE aRes Integer;
  SELECT c_id INTO aRes FROM xcountry where c_name=aName LIMIT 1;  
  RETURN aRes;
END

CREATE PROCEDURE `xinsert_test`(IN val varchar(200), IN country varchar(200))
BEGIN
  declare cid integer default xget_country_id(country);
  insert into xtest values(val,cid);                                                                                      
END


CREATE PROCEDURE `xinsert_test2`(IN val varchar(200), IN country varchar(200))
BEGIN
  insert into xtest select val, c_id from xcountry where c_name=country;
END


Вызывающий код:
Код


        String[] queries= {
                "insert into xtest select ?, c_id from xcountry where c_name=?" 
                ,"insert into xtest values(?, xget_country_id(?))" 
                ,"call xinsert_test(?,?)"
                ,"call xinsert_test2(?,?)"
                };
        String[] countries= {
                "Russia", 
                "Switzerland"};
        
        int NumPasses = 4;
        int NumRows=100000;
        
        
        System.out.printf("Test started for %d rows per pass\n",NumRows);
        
        try {
          Class.forName("com.mysql.jdbc.Driver").newInstance();
          Connection conn = DriverManager.getConnection(ConnectString);
          conn.setAutoCommit(false);
          for(int pass=0; pass<NumPasses; pass++){
              for(int i=0; i<queries.length; i++){
                  String s=queries[i];
                  long passStarted = System.currentTimeMillis();

                  PreparedStatement stmt = conn.prepareStatement(s);
                  for(int rowN=0; rowN<NumRows; rowN++){
                    stmt.setString(1, String.valueOf(pass)+":"+String.valueOf(i)+":"+String.valueOf(rowN));
                    stmt.setString(2, countries[rowN&1]);
                    stmt.execute();
                    //stmt.executeQuery();
                  }
                  if(!conn.getAutoCommit()) conn.commit(); 
                  long passFinished = System.currentTimeMillis();
                  System.out.printf("  Pass %d query %d passed for %d ms\n",pass,i,(passFinished-passStarted));
              }
          }
        } catch (SQLException ex) {
            // handle any errors
            System.out.println("SQLException: " + ex.getMessage());
            System.out.println("SQLState: " + ex.getSQLState());
            System.out.println("VendorError: " + ex.getErrorCode());
        } catch (Exception ex) {
          // handle any errors
          System.out.println("Exception: " + ex.getMessage());
        }        
        System.out.printf("Test finished\n");



Как видим, четыре разных запроса по-разному вставляют строку:
0: insert into xtest select ?, c_id from xcountry where c_name=? 
  - простой запрос, который я рекомендовал
1: insert into xtest values(?, xget_country_id(?))
  - запрос извлекающий ИД страны вызовом функции
2: call xinsert_test(?,?)
  - процедура, идущая по пути автора треда и вызывающая функцию для получения ИДа
3: call xinsert_test2(?,?)
  - Такой же запрос, как и в случае 0, только зачем-то упакованный в процедуру

Результат теста:

При включенном автокоммите:

Test started for 1000 rows per pass
  Pass 0 query 0 passed for 26438 ms
  Pass 0 query 1 passed for 29344 ms
  Pass 0 query 2 passed for 30265 ms
  Pass 0 query 3 passed for 28360 ms
  Pass 1 query 0 passed for 27109 ms
  Pass 1 query 1 passed for 30047 ms
  Pass 1 query 2 passed for 30172 ms
  Pass 1 query 3 passed for 28015 ms
  Pass 2 query 0 passed for 28875 ms
  Pass 2 query 1 passed for 30125 ms
  Pass 2 query 2 passed for 29797 ms
  Pass 2 query 3 passed for 27172 ms
  Pass 3 query 0 passed for 30344 ms
  Pass 3 query 1 passed for 30141 ms
  Pass 3 query 2 passed for 29218 ms
  Pass 3 query 3 passed for 27860 ms
Test finished


Выключаю автокоммит

Test started for 1000 rows per pass
  Pass 0 query 0 passed for 281 ms
  Pass 0 query 1 passed for 187 ms
  Pass 0 query 2 passed for 188 ms
  Pass 0 query 3 passed for 172 ms
  Pass 1 query 0 passed for 140 ms
  Pass 1 query 1 passed for 172 ms
  Pass 1 query 2 passed for 188 ms
  Pass 1 query 3 passed for 156 ms
  Pass 2 query 0 passed for 156 ms
  Pass 2 query 1 passed for 157 ms
  Pass 2 query 2 passed for 203 ms
  Pass 2 query 3 passed for 156 ms
  Pass 3 query 0 passed for 156 ms
  Pass 3 query 1 passed for 406 ms
  Pass 3 query 2 passed for 235 ms
  Pass 3 query 3 passed for 156 ms
Test finished

Быстровато, увеличил количество инсертов

Test started for 100000 rows per pass
  Pass 0 query 0 passed for 12046 ms
  Pass 0 query 1 passed for 12563 ms
  Pass 0 query 2 passed for 13812 ms
  Pass 0 query 3 passed for 12703 ms
  Pass 1 query 0 passed for 11953 ms
  Pass 1 query 1 passed for 12907 ms
  Pass 1 query 2 passed for 16171 ms
  Pass 1 query 3 passed for 12891 ms
  Pass 2 query 0 passed for 12125 ms
  Pass 2 query 1 passed for 12891 ms
  Pass 2 query 2 passed for 16093 ms
  Pass 2 query 3 passed for 13047 ms
  Pass 3 query 0 passed for 11657 ms
  Pass 3 query 1 passed for 13203 ms
  Pass 3 query 2 passed for 15968 ms
  Pass 3 query 3 passed for 13032 ms
Test finished

Добавил DETERMINISTIC в определение функции

Test started for 100000 rows per pass
  Pass 0 query 0 passed for 11875 ms
  Pass 0 query 1 passed for 12594 ms
  Pass 0 query 2 passed for 13812 ms
  Pass 0 query 3 passed for 12922 ms
  Pass 1 query 0 passed for 11766 ms
  Pass 1 query 1 passed for 12906 ms
  Pass 1 query 2 passed for 14406 ms
  Pass 1 query 3 passed for 12781 ms
  Pass 2 query 0 passed for 11828 ms
  Pass 2 query 1 passed for 13032 ms
  Pass 2 query 2 passed for 16297 ms
  Pass 2 query 3 passed for 12421 ms
  Pass 3 query 0 passed for 12141 ms
  Pass 3 query 1 passed for 13156 ms
  Pass 3 query 2 passed for 14266 ms
  Pass 3 query 3 passed for 12844 ms
Test finished


ЧТД

PS

На всякий случай, статус базы:


SSL:                    Not in use
Using delimiter:        ;
Server version:         5.0.22-community-max-nt
Protocol version:       10
Connection:             localhost via TCP/IP
Server characterset:    utf8
Db     characterset:    utf8
Client characterset:    utf8
Conn.  characterset:    utf8
TCP port:               3306
Uptime:                 23 hours 36 min 42 sec


Это сообщение отредактировал(а) 3x3 - 3.10.2006, 03:34


--------------------
Зачем платить больше,
когда можно заплатить дважды?
PM   Вверх
Sun
Дата 3.10.2006, 09:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



Цитата(3x3 @  2.10.2006,  19:38 Найти цитируемый пост)
А у вас аватар не просто так выбран? По SunOS можно обратиться с вопросиком?

Можно, правда я с ней не работал  smile  Работал только с FreeBSD и Linux. Аватар выбран не случайно - он соотвествует моему нику в этом форуме.

Что касается приведенного кода - я наконец-то понял к чему вы клоните. То-есть вы ничего не имеете против самих хранимых процедур, вы просто против их вызова в теле запроса и говорите что использовать вложенные запросы гораздо эффективнее. С этим спорить не буду, так как не проводил бэнчмарков по сабжу. Единственно добавлю что вложенных запросов также стоит избегать, а по возможности использовать JOIN.
Код

SELECT person.id, person.name FROM person
INNER JOIN country ON country.id=person.country_id
INNER JOIN continent ON country.continent_id=continent.id AND continent.name='Australia'
WHERE person.sex='M' ;



--------------------
Account removed
PM MAIL   Вверх
3x3
Дата 3.10.2006, 10:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 261
Регистрация: 17.9.2006

Репутация: 5
Всего: 8



Цитата(Sun @ 3.10.2006,  09:39)
Цитата(3x3 @  2.10.2006,  19:38 Найти цитируемый пост)
А у вас аватар не просто так выбран? По SunOS можно обратиться с вопросиком?

Можно, правда я с ней не работал  smile  Работал только с FreeBSD и Linux. Аватар выбран не случайно - он соотвествует моему нику в этом форуме.


А, ну ладно тогда, я в соответствующем разделе спросил..

Цитата

Что касается приведенного кода - я наконец-то понял к чему вы клоните. То-есть вы ничего не имеете против самих хранимых процедур, вы просто против их вызова в теле запроса и говорите что использовать вложенные запросы гораздо эффективнее. 


Поздравляю. Утро вечера мудренее.

Цитата

С этим спорить не буду, так как не проводил бэнчмарков по сабжу. Единственно добавлю что вложенных запросов также стоит избегать, а по возможности использовать JOIN.
Код

SELECT person.id, person.name FROM person
INNER JOIN country ON country.id=person.country_id
INNER JOIN continent ON country.continent_id=continent.id AND continent.name='Australia'
WHERE person.sex='M' ;



Не люблю этот синтаксис, и не знаю что он такого даёт в повседневном использовании. Мне больше нравится когда таблицы в запросе рядом через запятую перечислены smile 



--------------------
Зачем платить больше,
когда можно заплатить дважды?
PM   Вверх
Sun
Дата 3.10.2006, 11:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



Цитата(3x3 @  3.10.2006,  07:46 Найти цитируемый пост)
Не люблю этот синтаксис, и не знаю что он такого даёт в повседневном использовании. Мне больше нравится когда таблицы в запросе рядом через запятую перечислены smile 

Такой запрос отрабатывает более быстро чем если вы укажите через запятую или как вложенный запрос.


--------------------
Account removed
PM MAIL   Вверх
boroda
Дата 3.10.2006, 11:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 2.12.2005
Где: Киев

Репутация: 1
Всего: 1



Спасибо всем. Но в данном случае я не могу отказаться от процедур. Опять вопрос у меня был не в том что лучше, а что хуже. Вопрос был почему так работает а этак не работает. Но всеравно спасибо, было действительно интересно
PM MAIL   Вверх
3x3
Дата 3.10.2006, 11:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 261
Регистрация: 17.9.2006

Репутация: 5
Всего: 8



Цитата(Sun @ 3.10.2006,  11:04)
Цитата(3x3 @  3.10.2006,  07:46 Найти цитируемый пост)
Не люблю этот синтаксис, и не знаю что он такого даёт в повседневном использовании. Мне больше нравится когда таблицы в запросе рядом через запятую перечислены smile 

Такой запрос отрабатывает более быстро чем если вы укажите через запятую или как вложенный запрос.

Вот только вопрос - почему? 
Я вижу только одну потенциальную причину - это то, что в запросе вы явно задаёте оптимизатору по какому набору данных осуществлять внешний цикл, а по каким - вложенные.  Т.е. в общем случае выигрыш должен быть на RDBMS, с оптимизатором, ничего не знающим про свои данные и, соответственно, неспособным полноценно оптимизировать план запроса?

Добавлено @ 12:04 
Цитата(boroda @ 3.10.2006,  11:53)
Спасибо всем. Но в данном случае я не могу отказаться от процедур. Опять вопрос у меня был не в том что лучше, а что хуже. Вопрос был почему так работает а этак не работает.

Работающие процедуры приведены в коде бенчмарка..
Я бы на вашем месте их бенчмарком у себя и тестировал. Там, возможно, и у вас не null возвращается, а исключение. Там какие-то грабли с разграничением полномочий мне повстречались.




Цитата

Но всеравно спасибо, было действительно интересно

Ну теперь мне уже и самому интересно стало


--------------------
Зачем платить больше,
когда можно заплатить дважды?
PM   Вверх
Sun
Дата 3.10.2006, 13:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Account removed
***


Профиль
Группа: Экс. модератор
Сообщений: 1611
Регистрация: 14.8.2002

Репутация: 2
Всего: 48



Цитата(3x3 @  3.10.2006,  08:54 Найти цитируемый пост)
Я вижу только одну потенциальную причину - это то, что в запросе вы явно задаёте оптимизатору по какому набору данных осуществлять внешний цикл, а по каким - вложенные.  Т.е. в общем случае выигрыш должен быть на RDBMS, с оптимизатором, ничего не знающим про свои данные и, соответственно, неспособным полноценно оптимизировать план запроса?

Нельзя слишком доверять оптимизаторам. Как показывает практика, запросы с перечисленными через запятую таблицами отрабатывают медленней и уж тем более вложенные запросы, чем объединенные через JOIN. Особенно на больших объёмах. 


--------------------
Account removed
PM MAIL   Вверх
Страницы: (3) [Все] 1 2 3 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема »


 




[ Время генерации скрипта: 0.1607 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.