|
execute statement: как определить затраты на prepare ? (в trace-логе мало инфы)
|
|||
---|---|---|---|
#18+
hi all Дано: 1. Таблица t_list с двумя полями (id, f01), одно из которых ПК, в ней 50 тыс строк Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.
2. Скрипт с именем 'es_nobind.sql', выполняющий в цикле 10 вызовов execute statement с простым селектом из t_list одной строки. На каждой итерации формируется новое выражение, что вызывает, кончено же, лишние prepare: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
3. Скрипт с именем 'es_bind.sql' выполняющий аналогичный цикл, но в нём уже используется привязка параметра и выражение препарится один раз: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.
4. Содержимое конфига трейса: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
Теперь запускаю ISQL и в нём ввожу на выполнение сначала es_nobind.sql, затем es_bind.sql. Далее открываю лог трейса и вижу одинаковую статистику для ОБОИХ скриптов: 1) на первой итерации получилось 3 read, 13 fetches 2) на всех последующих итерациях - 1 reads, 5 fetches При выполнении скрипта es_nobind.sql временнЫе затраты на препаре для первой итерации (select f01 from t_list where id=10) оказались 6 мс, для всех последующих (select f01 from t_list where id=9, 8, 7 etc) - 0 мс. При выполнении скрипта es_bind.sql временнЫе затраты на препаре выражения select f01 from t_list where id=? составили 5 ms и выполнялись они, ес-сно, однократно. Код: plaintext
Теперь меняю количество итераций с 10 на 50'000, отрубаю трейс этой базы, перезапускаю ФБ. Снова запускаю ISQL и в нём опять два скрипта. Вижу следующее: Код: 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.
Понятно, что различие времени вып-я в 6 раз связано именно с prepare выражения, которое 50 тыс раз создается по-новой и подсовывается на выполнение в ES. Непонятно другое: а откуда вылезло такое расхождение в числе фетчей на 50 тыс итерациях, если на 10 (десяти) итерациях его не было вообще ? Вот фрагмент из трейса для препаре: 2011-08-08T00:37:05.8750 (428:020DE01C) PREPARE_STATEMENT C:\1INSTALL\FIREBIRD\DATA\TEST3.FDB (ATT_16, SYSDBA:NONE, NONE, XNET:BALAHA) C:\1INSTALL\FIREBIRD\FB_2_5\bin\isql.exe:804 (TRA_50189, CONCURRENCY | WAIT | READ_WRITE) Statement 38: ------------------------------------------------------------------------------- select f01 from t_list where id=10 6 ms Почему здесь нет фетчей ? Разве ФБ не должен проверить хотя бы существование объекта (t_list) в БД, мои права на селект из него, наличие в нём полей f01 и ID ? PS. В аттаче - трейс для первого прогона, где был цикл на 10 итераций. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.08.2011, 00:56 |
|
execute statement: как определить затраты на prepare ? (в trace-логе мало инфы)
|
|||
---|---|---|---|
#18+
Таблоид откуда вылезло такое расхождение в числе фетчей на 50 тыс итерациях, если на 10 (десяти) итерациях его не было вообще ? Вру. Это в трейсе не было расхождений. А в ISQL очень даже и есть: 54 для es_bind.sql и 90 для es_nobind.sql. Влад говорил ранее: hvladТрейс оперирует индивидуальными для запроса счётчиками и измеряет только выполнение указанной операции <...> [ISQL оперирует] Глобальными, полученными от isc_database_info. Причём первый раз он их берёт до isc_dsql_prepare, а второй - после isc_dsql_free_statement. В общем, 2 hvlad : есть ли возможность показывать в трейсе затраты на prepare (значения reads, fetches, которые потребовались на него) ? ... |
|||
:
Нравится:
Не нравится:
|
|||
08.08.2011, 08:31 |
|
execute statement: как определить затраты на prepare ? (в trace-логе мало инфы)
|
|||
---|---|---|---|
#18+
Таблоидесть ли возможность показывать в трейсе затраты на prepare (значения reads, fetches, которые потребовались на него) ?Мой ответ тебе вряд ли понравится :) Затраты на prepare учитываются в статистике системных запросов, которые в трейсе не показываются. Соответственно я могу только пообещать добавить трассировку системных запросов. Но они написаны на GDML и их текстов в движке нет, так что вряд ли эта информация будет кому-то сильно полезна (кроме разве что нас самих). ... |
|||
:
Нравится:
Не нравится:
|
|||
08.08.2011, 10:32 |
|
execute statement: как определить затраты на prepare ? (в trace-логе мало инфы)
|
|||
---|---|---|---|
#18+
hvladих текстов в движке нет... а где? ... |
|||
:
Нравится:
Не нравится:
|
|||
08.08.2011, 11:45 |
|
execute statement: как определить затраты на prepare ? (в trace-логе мало инфы)
|
|||
---|---|---|---|
#18+
WildSeryhvladих текстов в движке нет... а где? В исходниках (.epp) до обработки препроцессором. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.08.2011, 12:14 |
|
execute statement: как определить затраты на prepare ? (в trace-логе мало инфы)
|
|||
---|---|---|---|
#18+
как тестировавший терабайтную базу, могу заявить, что основные затраты при prepare это скан кардинальности таблиц (pointer pages), поэтому, пока речь не идет о базе в 100 гиг и очень больших таблицах, беспокоиться по поводу затрат на prepare не очень нужно. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.08.2011, 19:33 |
|
execute statement: как определить затраты на prepare ? (в trace-логе мало инфы)
|
|||
---|---|---|---|
#18+
kdvосновные затраты при prepare это скан кардинальности таблиц (pointer pages)да,у нас таблицы поменьше, конечно. Но ведь этот execute statement в цикле, а цикл может случиться разным (по числу итераций... ;-)) ... |
|||
:
Нравится:
Не нравится:
|
|||
08.08.2011, 19:44 |
|
execute statement: как определить затраты на prepare ? (в trace-логе мало инфы)
|
|||
---|---|---|---|
#18+
FB 3.0.5.33220 А есть информация, как долго сохраняется prepare для execute statement с параметрами - до конца транзакции, коннекта? И доступны ли запросы, препарированные execute statement в одной транзакции, другим транзакциям, коннектам? И есть ли ограничение на кол-во препарированных запросов внутри процедуры/триггера, транзакции? Интересуюсь с тем, чтобы понять, стоит ли переделывать существующие execute statement без параметров на варианты с параметрами с целью ускорения работы, или оставить как есть, раз prepare и так быстро работает. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.08.2020, 14:05 |
|
execute statement: как определить затраты на prepare ? (в trace-логе мало инфы)
|
|||
---|---|---|---|
#18+
ggreggory, препарированные запросы всегда привязаны к соединению, а не транзакции, так что ggreggoryИ доступны ли запросы, препарированные execute statement в одной транзакции, другим транзакциям, коннектам? другим коннектам точно нет. Насчёт остального не знаю точно, но скорее всего да. С внешними соединениями есть нюансы, они живут либо до конца текущей транзакции, либо сразу закрываются для автономок. Пул внешних соединений появился только в 4.0. ... |
|||
:
Нравится:
Не нравится:
|
|||
25.08.2020, 14:21 |
|
execute statement: как определить затраты на prepare ? (в trace-логе мало инфы)
|
|||
---|---|---|---|
#18+
Спасибо! Буду думать-тестить.... ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2020, 11:16 |
|
execute statement: как определить затраты на prepare ? (в trace-логе мало инфы)
|
|||
---|---|---|---|
#18+
От компонентов может зависеть. При использовании ibx препапированные запросы привязаны к транзакции. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2020, 19:17 |
|
execute statement: как определить затраты на prepare ? (в trace-логе мало инфы)
|
|||
---|---|---|---|
#18+
DmSer От компонентов может зависеть. При использовании ibx препапированные запросы привязаны к транзакции. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2020, 21:57 |
|
execute statement: как определить затраты на prepare ? (в trace-логе мало инфы)
|
|||
---|---|---|---|
#18+
DmSer, Мой вопрос был только о prepare для execute statement, а не о prepare на стороне клиента. Пока, мне кажется, что prepare сохраняется вообще только для одного запроса. Ниже 3 тестовых процедуры. TEST_1 содержит один запрос, у меня выполняется 62 миллисекунды TEST_2 содержит два чередующихся запроса, 422 миллисекунды TEST_3 содержит 10000 различных запросов, работает примерно то же время что и TEST_2 т.е. начиная с двух запросов нет никакой разницы во времени выполнения, prepare делается каждый раз, как встречается новый запрос. create or alter procedure TEST_1 as declare variable I integer; declare variable TMP integer; declare variable S varchar(1000); begin i = 0; while (i <= 10000) do begin s = 'select 0 from RDB$DATABASE where ' || 0 || ' = ?'; i = i + 1; execute statement (s) (0) into tmp; end end^ create or alter procedure TEST_2 as declare variable I integer; declare variable TMP integer; declare variable S varchar(1000); begin i = 0; while (i <= 10000) do begin s = 'select 0 from RDB$DATABASE where ' || bin_and(i, 1) || ' = ?'; i = i + 1; execute statement (s) (bin_and(i, 1)) into tmp; end end^ create or alter procedure TEST_3 as declare variable I integer; declare variable TMP integer; declare variable S varchar(1000); begin i = 0; while (i <= 10000) do begin s = 'select 0 from RDB$DATABASE where ' || i || ' = ?'; i = i + 1; execute statement (s) (i) into tmp; end end^ ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2020, 23:22 |
|
execute statement: как определить затраты на prepare ? (в trace-логе мало инфы)
|
|||
---|---|---|---|
#18+
ggreggory, гм. test2 и test3 отличаются только передачей параметра в exec statement (да и test1 тоже, что не соответствует вашему тексту). Но в во всех трех случаях оно 10к раз перепрепарируется. Получается, идет сравнение скорости where ' || bin_and(i, 1) || ' = ?'; ... execute statement (s) (bin_and(i, 1)) into tmp; и where ' || i || ' = ?'; ... execute statement (s) (i) into tmp; В ФБ нет кэша препарированных запросов. Тем более в контексте процедуры. Если клиент может использовать хэндл препарированного запроса, то у ES никакого "хэндла" нет. Тем более, откуда ФБ должен догадаться, что в переменной s всё время один и тот же запрос? Он бы мог, если бы был кэш запросов вообще (по контрольной сумме запроса, например). ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2020, 23:50 |
|
execute statement: как определить затраты на prepare ? (в trace-логе мало инфы)
|
|||
---|---|---|---|
#18+
ggreggory, У тебя ddl, тут вообще другая история, тёмная для меня. Я такие "запросы" стараюсь выполнять по отдельности в отдельных транзакциях, обрамляя коммитами. ... |
|||
:
Нравится:
Не нравится:
|
|||
26.08.2020, 23:52 |
|
execute statement: как определить затраты на prepare ? (в trace-логе мало инфы)
|
|||
---|---|---|---|
#18+
kdv Но в во всех трех случаях оно 10к раз перепрепарируется. А я пришёл к выводу, что в TEST_1 запрос препарируется единократно. А в TEST_2 и TEST_3 препарируется каждый раз, поэтому и возникает разница. kdv Получается, идет сравнение скорости where ' || bin_and(i, 1) || ' = ?'; ... execute statement (s) (bin_and(i, 1)) into tmp; и where ' || i || ' = ?'; ... execute statement (s) (i) into tmp; Вы можете проверить у себя эти две процедуры. Я не нашёл существенной разницы в скорости их работы. Но вот процедура TEST_1 работает в 7 раз быстрее, из чего я предположил, что в ней prepare делается только один раз. kdv В ФБ нет кэша препарированных запросов. Тем более в контексте процедуры. Если клиент может использовать хэндл препарированного запроса, то у ES никакого "хэндла" нет. Тем более, откуда ФБ должен догадаться, что в переменной s всё время один и тот же запрос? Он бы мог, если бы был кэш запросов вообще (по контрольной сумме запроса, например). Вот что пишут про это в инструкции: In previous versions, if EXECUTE STATEMENT occurred in a loop, the SQL statement would be prepared, executed and released upon every iteration. In Firebird 2.5 and above, such a statement is only prepared once, giving a huge performance benefit. (ссылка https://www.firebirdsql.org/refdocs/langrefupd25-psql-execstat.html ... |
|||
:
Нравится:
Не нравится:
|
|||
27.08.2020, 01:13 |
|
execute statement: как определить затраты на prepare ? (в trace-логе мало инфы)
|
|||
---|---|---|---|
#18+
ggreggory, До появления пула (в fb4) жизнь внешнего коннекта была привязана - к локальной (юзерской) тр-ции, если внешняя тр-ция - COMMON (по-умолчанию), или - к жизни самого запроса, если внешняя тр-ция - AUTONOMOUS. У тебя - COMMON тр-ция, поэтому коннект, который использует ES, живёт до окончания юзерской тр-ции и может быть использован повторно. Далее. Внешний коннект кеширует до 16 выполнявшихся запросов (сравнивается полный текст, как его передали в ES). Но у тебя запросы SELECT, из которых нет фетчей - их нельзя повторно использовать, т.к. они активны. Это жуткий пример как делать НЕ НАДО. Посмотри мониторингом - сколько у тебя живых запросов после такого ES (до коммита тр-ции). Ну и напоследок - трейс покажет и сколько раз был выполнен prepare, и сколько времени он занял. PS не проверял ... |
|||
:
Нравится:
Не нравится:
|
|||
27.08.2020, 02:06 |
|
execute statement: как определить затраты на prepare ? (в trace-логе мало инфы)
|
|||
---|---|---|---|
#18+
Поспешил с критикой немного, всё там закрывается и повторно используется (по мере возможности). Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
Код: plaintext 1. 2. 3. 4.
Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
Код: plaintext 1. 2. 3. 4. 5.
Код: sql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
Код: plaintext 1. 2. 3. 4. 5.
... |
|||
:
Нравится:
Не нравится:
|
|||
27.08.2020, 02:23 |
|
execute statement: как определить затраты на prepare ? (в trace-логе мало инфы)
|
|||
---|---|---|---|
#18+
hvlad Внешний коннект кеширует до 16 выполнявшихся запросов (сравнивается полный текст, как его передали в ES). Спасибо за наводку! Теперь картина вырисовывается. hvlad всё там закрывается и повторно используется (по мере возможности). Да, так и есть. Стал разбираться почему вчера у меня тайминг у 2-ой процедуры другой получился. Оказывается я не подтвердил транзакцию от предыдущего эксперимента и у меня просто исчерпалось кол-во запросов. Если транзакцию подтверждать, то всё работает точь-в-точь как вы написали. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.08.2020, 16:30 |
|
|
start [/forum/topic.php?fid=40&tid=1560267]: |
0ms |
get settings: |
8ms |
get forum list: |
12ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
143ms |
get topic data: |
107ms |
get forum data: |
3ms |
get page messages: |
72ms |
get tp. blocked users: |
1ms |
others: | 20ms |
total: | 372ms |
0 / 0 |