|
|
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
Я только собираюсь переехать с BDE (Paradox) на FB. И вот решил поэкспериментировать ... Сделал тестовую программу, которая делает вставку записей в таблицу. Записи вставляются группами, при этом засекается время на вставку группы записей. Перед вставкой группы запускается транзакция, а по завершении вставки группы транзакция подтверждается. В качестве сервера использовал FB 1.5, программу писал на Delphi 5, в тестах использовал компоненты IBX 5.04 и FibPlus 5.02. Сервер и клиент рассполагались на одной машине. Коннект к БД был как к сетевой, т.е. 127.0.0.1:D:\test.fdb Вставка делалась так 10 раз по 50 записей, 10 раз по 500 записей, 10 раз по 1000 записей, 10 раз по 5000, 10 раз по 10000 записей. Время для каждой из групп усреднялось, т.е. в результате получалось среднее время для вставки одной записи для группы из 50, 500, 1000, 5000, 10000 записей. Так вот проявляется странная закономерность: - если вставку записи в таблицу делать с помощью sql запроса находящегося в клиентском приложении, то запрос выполняется в 1,5-2 раза быстрее и проц нагружается на 30%-40% меньше, чем если тот же делать с помощью хранимой процедуры (а странно ведь говорят, что ХП хранятся на сервере и выполняются быстрее ); - чем больше записей в таблице, тем больше среднее время на вставку одной записи в группах с небольшим количеством записей 50, 500, 1000. т.е. получается, что в маленькие таблицы (около 10000 записей) выгодно вставлять записи группами по 500 записей, а в средние таблицы (около 1000000 записей) - группами по 5000 - 10000 записей. Хотелось бы найти объяснения этим двум явлениям. Так же как я понял, что не хорошо как раньше выдавать все записи на клиента по эго запросу, и что записи нужно выдавать как бы страницами и для этого использовать конструкцию Select First x Skip y .... якобы она позволяет не нагружать сервер и сократить трафик .... Но как она может сократить трафик и разгрузить сервер при ее текущей реализации, мне не ясно. Допустим, клиент запросил Архив параметров за месяц с помощью запроса "select .... from ... where ..... order by ...." пусть кол-во записей удовлетворяющих этому запросу - 500000. Чтобы не выдавать клиенту такого количества записей за один раз нужно добавить в запрос First x Skip y. Пусть записи будут выдаваться группами по 5000 записей, т.е. клиенту нужно будет вызвать запрос 100 раз. при этом насколько я понимаю трафик ни сколько не сократится т.к. клиент, если не запарится жать на next, получит таки свои 500000 записей, а суммарная нагрузка на сервер возрастет. т.к. для первого запроса x=5000, y=0, сервер выберет и отправит клиенту 5000 записей; для второго запроса x=5000, y=5000, сервер выберет 10000 записей и отправит клиенту последние 5000 записей; ... для 100 - го запроса x=5000, y=495000, сервер выберет 500000 записей и отправит клиенту последние 5000 записей. т.е. начиная со второго запроса сервер будет вынужден выбирать лишние записи: для второго запроса 5000, для третьего 10000, ... для 100 - 495000. Получается, нагрузка на сервер возрастет в арифметической прогрессии. И помимо 500000 записей сервер еще выберет (5000+495000)*99/2 записей. т.е. получается, что выдавать записи по страницам не выгодно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.03.2004, 02:37 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
по поводу first/skip думаю ты прав. тут уместнее делать выборку порции другим способом. делать select какой нужно, без ограничений на количество строк. но фетчить только столько строк, сколько нужно отобразить пользователю. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.03.2004, 03:16 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
авторТак же как я понял, что не хорошо как раньше выдавать все записи на клиента по эго запросу, и что записи нужно выдавать как бы страницами и для этого использовать конструкцию Select First x Skip y .... якобы она позволяет не нагружать сервер и сократить трафик .... Но как она может сократить трафик и разгрузить сервер при ее текущей реализации, мне не ясно. Она позволяет только сократить транспортный трафик. Насчет разгрузки сервера - выигрыш есть, но он очень практически незаметен. Ты абсолютно правильно обрисовал механизм работы сервера в случае SKIP. Просто тихо пропустить записи в холостом цикле внутри сервера хоть чуть-чуть, но выгоднее, чем формировать из них пакеты для фетча с клиента (с точки зрения CPU/памяти). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.03.2004, 10:09 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
У меня вставка поллимона записей через ХП идет быстрее, чем через SQL. Данные вставляю в одной транзакции, ХП подготавливается перед началом цикла. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.03.2004, 10:16 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
А мне вообще не понятно как такое может быть : авторДопустим, клиент запросил Архив параметров за месяц с помощью запроса "select .... from ... where ..... order by ...." пусть кол-во записей удовлетворяющих этому запросу - 500000. И что же клиент собирается делать с этими 500000 записями (даже если по 5000)? Best regards, Dnico. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.03.2004, 10:22 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
Найти нужную запись в отсортированном наборе не так уж и сложно. Даже при 3 лимонах записей. Другое дело сколько прочитанные записи в памяти будут занимать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.03.2004, 10:53 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
DnicoИ что же клиент собирается делать с этими 500000 записями В банки солить. Мне вообще непонятно зачем к серверу делать 100 запросов начиная с "x=5000, y=0" до "x=5000, y=495000". Если 500000 записей соответствуют условию запроса то они и должны выбратся. А порциями выбирать... Просто немогу себе предсавить задачу где бы это понадобилось. Кстати очень интересно посмотреть на полный скрипт создания базы и исходники клиента в которых вставка через хранимую процедуру работает медленее чем вставка с клиента. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.03.2004, 11:06 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
По поводу: AndreyМне вообще непонятно зачем к серверу делать 100 запросов начиная с "x=5000, y=0" до "x=5000, y=495000". Если 500000 записей соответствуют условию запроса то они и должны выбратся. А порциями выбирать... Просто немогу себе предсавить задачу где бы это понадобилось. Вопрос снимается. Придумал задачу где это полезно :) При построении 2,3,...n страниц например этого форума... Но исходники всеравно увидеть хочется. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.03.2004, 11:32 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
Вот исходная таблица, в которую происходит вставка записей Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. Для вставки записей со стороны клиента я использовал следующий запрос (он был помещен в TpFibQuery и выполнялся с помощью метода ExecQuery, приблизительно такая же реализация этого запроса была и для IBX). Код: plaintext 1. 2. 3. 4. 5. 6. Скорость выполнения такого запроса при вставке записей группами по 50, 500, 1000, 5000 записей была в 1,5-2 раза быстрее, а загрузка процессора на 30%-40% меньше чем при выполнении любой из двух следующих XP, (они отличаются только способом заполнения поля DAT, в одном случае значение для поля DAT формируется у клиента, а в другом на - сервере): // Первый вариант XP Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. // Второй вариант XP Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. Хранимые процедуры выполнялись как с помощью TpFibStoredProc из FibPlus так и с помощью TIBStoredProc из IBX. Для выполнения процедуры использовался метод ExecProc. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.03.2004, 13:03 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
Хм... Вообще то я думал что процедуры были типа: Код: plaintext 1. А в том варианте что вы предложили... первое обьяснение, что приходит на ум это то что FB при вызове процедуры проверяет валидность параметров, а потом при вставке опять проверяет валидность параметров (валидность в смысле соответствие типа данных, а не проверки по различным check-ам). Но это только домыслы. Про вставку: тут есть статья. В пункте 4 сказано только про выборки, но замедление так же заметно и на вставках в такие таблици. Хотя конечно в вашем случае это врядли влияет. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.03.2004, 13:27 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
Вопрос снимается. Придумал задачу где это полезно :) При построении 2,3,...n страниц например этого форума... Мне кажется эту задачу нужно с другого конца решать несколько. Именно сделать промежуточную таблицу и работать с ней через between. Тогда и нагрузки не будет. Так что задача некорректная :-) Интересно было бы увидеть именно задачу где именно требуется, причем без этого обойтись нельзя, First...Skip ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.03.2004, 12:42 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
Хорошо с Select First X Skip Y все ясно: что такую фитчу лучше совсем не использовать. Остается только один вопрос как заставить XP работать с такой же скорость к и у запроса на вставку со стороны клиента. Да пробовал удалить индексы, не помогло. Видимо дело в том Andrey_ что FB при вызове процедуры проверяет валидность параметров, а потом при вставке опять проверяет валидность параметров (валидность в смысле соответствие типа данных, а не проверки по различным check-ам). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.03.2004, 23:26 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
Andrew Kruchininсделать промежуточную таблицу и работать с ней через between. Тогда и нагрузки не будет. Так что задача некорректная Хм... чет я не понял... Есть таблица Threads, в ней есть поле LastUpdate. И задача с показыванием второй страници форума решается четез 1 select: select First 50 Skip 50 from Threads А как по другому? И чтоб и красиво и быстро :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.03.2004, 12:17 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
Ввести поле 'номер сообщения' и выбирать between (n-1)*m+1 and n*m где n - номер страницы, m - количество сообщений на одну страницу. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.03.2004, 12:48 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
Промахнулся я немного... Я хотел сказать не select First 50 Skip 50 from Threads а select First 50 Skip 50 from Threads order by LastUpdate desc Тоесть набор тем страници формируется динамически исходя из времени последнего обновления. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.03.2004, 13:10 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
Andrey_ select First 50 Skip 50 from Threads order by LastUpdate desc А как по другому? И чтоб и красиво и быстро :) Ну все сразу обычно не получается, чтобы и быстро и красиво... Голова программистам дана именно для того чтобы решать нестандартные задачи, и пытатся сделать все сразу вообще нереально. Вот такой вариант чем плох? select txt.msg.text from msg_list left join txt_msg on (txt_msg.id=msg_list.id_msg) where msg_list.numer between ((:n-1)*:m+1) and (:n*:m) order by msg_list.numer desc Условие взято из сообщения hyh-а. Чем плох вариант? И не говори что он будет выполнятся медленнее - не поверю. И не настолько уж и страшный запрос. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.03.2004, 05:55 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
Andrew KruchininНу все сразу обычно не получается, чтобы и быстро и красиво... Вот такой вариант чем плох? И не говори что он будет выполнятся медленнее - не поверю. И не настолько уж и страшный запрос. Вариант не плох. Наверно плохоа моя постановка :) Итак: Есть таблица Threads. Запись соответствует ветке форума. В ней есть поле LastUpdate. В этом поле хранится время сообщения добавленого в эту ветку последним. При сортировке веток по дате изменения (которая в этом форуме стоит по умолчанию) очень легко получить нужную последовательность: select * from Threads order by LastUpdate desc Так мы получаем набор записей отсортированый по дате изменения, начиная с ветки которая была изменена последней . Для первой страници нам больше ничего и не надо. Обрабатываем 50 первых записей и закрываем запрос. А для того чтобы показать вторую страницу нам пришлось бы пропустить первые 50 записей и показать следующие 50 (с 51 по 100 в исходном наборе). Вот тут нам на выручку приходит First Skip. Выполнив: select First 50 Skip 50 from Threads order by LastUpdate desc Мы получим сразу 51 запись исходного набора, а первые 50 будут обработаны и отброшены на сервере. Теперь со временной таблицой msg_list (number integer, msg_id integer) Чтобы в ней были актуальные данные (список всех веток форума отсортированый по дате изменения) после каждого добавления нового сообщения эту таблицу прийдется перезаполнять запросами: delete from msg_list; // чистим таблицу gen_id(gen_number, -gen_id(gen_number, 0)); // обнуляем генератор insert into msg_list (number, msg_id) // заполняем таблицу select gen_id(gen_number, 1), Id from Threads order by LastUpdate; Почему. Потому что если вдруг в ветку которая находится на (допустим) 48 странице добавится сообщения то она автоматом должна стать первой веткой во всем форуме. Как видите с First Skip все и быстро и красиво, а с msg_list и медленно и э...не очень красиво :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.03.2004, 10:34 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
Andrey_после каждого добавления нового сообщения эту таблицу прийдется перезаполнять запросами: А это еще зачем? msg_list.numer в этом случае НЕ является уникальным и первичным ключем для данной таблицы а просто содержит порядковый номер в текущей теме. Думаю что вполне реально можно сделать так чтобы номера увеличивались автоматически. А почему бы и нет? Я извиняюсь что не все таблицы тут написал, но идея была именно такая. А табличка такая я думаю нужна к примеру msg_list (id integer, number integer, msg_id integer, id_subj integer) и триггер на всавку установить на txt_msg, где будет заполнятся и id и number автоматически. Хотя тут есть свои грабли, но их к примеру можно обойти через тот же генератор. К примеру вот так: Триггер на вставку нового сообщения while (gen_id(added_numer, 0)=1) do begin end gen_id(addad_numer, 1); select max(msg_list.numer)+1 from msg_list where id_subj=:id_subj into :new_numer; insert into msg_list (number, msg_id, id_subj) values (:new_number, new.id, new.subj_id); gen_id(addad_numer, -1); И не говори что некрасиво, по моему очень даже и неплохо получается :-) Правда тут конечно интересно - а как будет отрабатывать while, я просто так никогда не делал. Не будет ли он машину вешать? Если нет, то тогда это не страшно. Если да, то можно в принципе и другие способы придумать, главное чтобы не пропустить вариант когда одновременно попытаются добавится больше одного сообщения в одну тему. Чревато как бы... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.03.2004, 12:52 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
Да, если уж на то пошло, то и правда - как будет работать холостой while? Или это плохо? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.03.2004, 12:54 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
Ох батенька... В таблице Thread запись соответствует ВЕТКЕ форума Ветке! А не сообщению в ветке . Ведь как-то динамически формируется 2 , 3 , 4 ... 51 страници этого форума.... А "холостой" цикл "while (gen_id(added_numer, 0)=1) do begin end" просто повесит сервер если added_numer=1. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.03.2004, 13:32 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
Ох батенька... В таблице Thread запись соответствует ВЕТКЕ форума Ветке! А не сообщению в ветке. Ведь как-то динамически формируется 2,3,4...51 страници этого форума.... А кто запрещает в этом случае древовидную структуру реализовать? А "холостой" цикл "while (gen_id(added_numer, 0)=1) do begin end" просто повесит сервер если added_numer=1. Ох, не поленился, проверил. Все работает нормально. Да, загрузка проца под 100%, ну и что? Параллельно выполнилось несколько запросов и ХП, тормоза если и есть, то не такие большие. Хотя согласен - вопрос спорный по поводу таких вещей. но мне кажется на уровне WEB-а это не так критично. Если правильно проиндексировать базу,то запрос на максимальное значение будет выполнятся не так долго. А вообще если завести вспомогательную таблицу (даже я думаю так будет лучше в этом случае), то вообще проблем не будет. Главное тормозить будет не так сильно как со Скипом. Вообще пример с First Skip высосан из пальца, как и способ его обхода - признаюсь :-) Просто хотел показать что решить эту задачу можно и без скипа, который сервак по любому нагрузит. P.S. Вот теперь сервак тормозить придется :-) Запустил ХП из под эксперта :-) Лень было как-то по другому пускать вообще, дольше. Ну да ладно ;-) Да, еще вдогонку - проц на машине 300, а стоит WinModem счас, обрыва не было, даже ни попыточки, хотя частенько если проц под 90 уходит уже модем захлебыватся начинает. Так что не так страшено похоже этот холостой цикл как кажется. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 12.03.2004, 13:51 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
Заключение о том, что хранимая процедура ВСЕГДА выполняется быстрее совершенно не верно. Любой подготовленный вами запрос, например, в Delphi клиенте будет передан на сервер и там откомпилирован. Будьте уверены что для операций вставки ( как впрочем и для других операций ) этот откомпилированный запрос будет короче и выполняться быстрее. чем SP моделирующая Insert-оператор. Хранимые процедуры хороши не тогда, когда они просто моделируют единственный оператор SQL, а когда одним оператором просто не обойтись и надо либо привлекать клиентский код или писать SP ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.04.2004, 12:20 |
|
||
|
Скорость выполнения хранимых процедур, а так же Select First X Skip Y
|
|||
|---|---|---|---|
|
#18+
Ну, не ужас, а "Ужас - ужас"! Ухи вянут! А предварительная компиляция запроса на сервере для кого придумана? Почему никто не сказал про команду Prepare при массовой обработке записей?! Счас ремень достану! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 28.04.2004, 12:26 |
|
||
|
|

start [/forum/topic.php?fid=40&msg=32439862&tid=1578741]: |
0ms |
get settings: |
6ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
170ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
76ms |
get tp. blocked users: |
1ms |
| others: | 200ms |
| total: | 487ms |

| 0 / 0 |
