|
|
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
Написалазапрос Код: plsql 1. 2. 3. 4. 5. 6. 7. Сделала индекс по функции CREATE INDEX FIRST_NAME ON EMPLOYEES(UPPER (FIRST_NAME)); ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Plan hash value: 3488509485 --------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 43 | 3 (0)| 00:00:01 | | 1 | NESTED LOOPS | | | | | | | 2 | NESTED LOOPS | | 1 | 43 | 3 (0)| 00:00:01 | | 3 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 1 | 27 | 2 (0)| 00:00:01 | |* 4 | INDEX RANGE SCAN | FIRST_NAME | 1 | | 1 (0)| 00:00:01 | |* 5 | INDEX UNIQUE SCAN | DEPT_ID_PK | 1 | | 0 (0)| 00:00:01 | | 6 | TABLE ACCESS BY INDEX ROWID | DEPARTMENTS | 1 | 16 | 1 (0)| 00:00:01 | --------------------------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 4 - access(UPPER("FIRST_NAME")='GUY') 5 - access("E"."DEPARTMENT_ID"="D"."DEPARTMENT_ID") 19 rows selected Пытаюсь прочитать. 1.Операция 4 получает доступ к таблице EMPLOYEES по индексу FIRST_NAME и возвращает ROWID для операции 3 2.Операция 5 получает доступ к таблице DEPARTMENTS по индексу DEPT_ID_PK возвращает ROWID для операции 2 3. Операция 2 выполняет соединения таблиц 4.Операция 1 отдает результат в операцию 0. ...Но как то коряво .... не понимаю, что происходит на 5 операции, помогите разобраться. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.10.2016, 18:09 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
План запроса читается снизу вверх. 6. Получаем роувиды таблицы департаментов. 5. Из этого множества построчно обходим (п. 2) и получаем роувиды таблицы департаментов, значение колонки DEPARTMENT_ID которой равно значениям колонки DEPARTMENT_ID таблицы сотрудников 4. Из таблицы сотрудников отбираем по индексу первого имени набор строк 3. Из полученного набора строк сотрудников получаем роувиды 2. Увязываем с построчным проходом департаментов набор из таблицы сотрудников - формируем по завершении каждого обхода набор значений, соответствующих 1 строке департаментов 1. Увязываем все наборы, полученные по каждой строке департамента в одну коллекцию 0. Показываем заданные поля из отобранной коллекции ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.10.2016, 21:52 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
FogelПлан запроса читается снизу вверх.Бред чуть более, чем полностью. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.10.2016, 22:05 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
ElicFogelПлан запроса читается снизу вверх.Бред чуть более, чем полностью. имеющий уши да услышит, не зрячий да прозреет, разум, полный формулировок не видит содержимого. фраза "Бред чуть более, чем полностью" указывает, что человек соврал на 100 процентов, то есть не прав полностью. однако тут, Элик, лажа в твоей формулировке, ибо я прав в том, что озвучил ( "План запроса читается снизу вверх" ), а то, что не озвучил , то и не бред, и не правда, а недосказанность - просто нулл в сообщении. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.10.2016, 22:42 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
Fogelибо я правДеточка, это популизм - хотеть казаться правым. Нездоровенький такой. Fogelв том, что озвучил ( "План запроса читается снизу вверх" ), а то, что не озвучил , то и не бред, и не правда, а недосказанность - просто нулл в сообщении.Да-да. На заборе тоже недосказанно было написано слово "мир" с тремя ошибками. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.10.2016, 23:07 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
murr31, Код: plsql 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. Каждый шаг плана проще всего объяснять как некую процедуру, вложенные шаги которой являются операциями-процедурами, запускаемыми/останавливаемые этой процедурой и постепенно возвращающие в нее свои результаты. Т.е. в твоем плане это будет так: 0. Запускается SELECT, который запускает NESTED LOOPS из шага 1; 1. NESTED LOOPS шага 1, запускает NESTED LOOPS из шага 2 и по возвращенным строкам(ROWIDs) оттуда выполняет шаг 6, т.е. достает оттуда строки по найденным роуайди из шага 2; 2. NESTED LOOPS шага 2 запускает процедуру из шага 3 (TABLE ACCESS BY INDEX ROWID) и по возвращенным строкам оттуда выполняет шаг 5, т.е. фильтрует эти строки по INDEX UNIQUE SCAN индекса DEPT_ID_PK 3. Шаг 3 - TABLE ACCESS BY INDEX ROWID - запускает шаг 4(INDEX RANGE SCAN) и по возвращенным оттуда ROWID достает строки из EMPLOYEES 4. Шаг 4 сканирует индекс FIRST_NAME через IRS(index range scan) по предикату: access(UPPER("FIRST_NAME")='GUY') ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.10.2016, 23:18 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
FogelПлан запроса читается снизу вверх. 6. Получаем роувиды таблицы департаментов. 5. Из этого множества построчно обходим (п. 2) и получаем роувиды таблицы департаментов, значение колонки DEPARTMENT_ID которой равно значениям колонки DEPARTMENT_ID таблицы сотрудников 4. Из таблицы сотрудников отбираем по индексу первого имени набор строк 3. Из полученного набора строк сотрудников получаем роувиды 2. Увязываем с построчным проходом департаментов набор из таблицы сотрудников - формируем по завершении каждого обхода набор значений, соответствующих 1 строке департаментов 1. Увязываем все наборы, полученные по каждой строке департамента в одну коллекцию 0. Показываем заданные поля из отобранной коллекцииЕшкин же ж кот, какой бред... ты бы сначала сам планы научился читать... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.10.2016, 23:20 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
murr31... Пытаюсь прочитать. 1.Операция 4 получает доступ к таблице EMPLOYEES по индексу FIRST_NAME и возвращает ROWID для операции 3 + (правильно), в текущем наборе данных e.rowid 2. выполняется операция 3 (| 3 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES ) , идущая по найденным на первом шаге e.rowid и добавляющая к текущему набору значения полей из E - E.employee_id, E.last_name, результат отдается на шаг |2| 3. выполняется шаг 2 | NESTED LOOPS |, в наличии E.employee_id, E.last_name, значения E.employee_id из текущей строки набора используются как параметр, отдаваемый на шаг |5| murr31 2 4.Операция 5 получает доступ к таблице DEPARTMENTS по индексу DEPT_ID_PK возвращает ROWID для операции 2 + (правильно), доступ осуществляется по значению E.department_id, полученному в операции |3|, Этот шаг завершает выполнение шага |2|, по выполнению которого обеспечивается наличие обеспечивает сохранение E.employee_id, E.last_name, D.ROWID в текущем выходном наборе, передавая результат на шаг |1| 5. Выполняем шаг | 1 | NESTED LOOPS, используя полученный D.ROWID как параметр, отдаваемый на шаг | 6 | TABLE ACCESS BY INDEX ROWID 6. Выполняем | 6 | TABLE ACCESS BY INDEX ROWID Завершение этого шага добавляет в выходной набор d.department_name и завершает шаг |1| 7. Результат отдаем на шаг 0, который выбирает из текущего рабочего набора требуемые E.employee_id, E.last_name, d.department_name ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.10.2016, 23:26 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
murr31Пытаюсь прочитатьДля начинающих вот тетенька подробно объясняет Execution Plans - Learn by Example Имеются некоторые неточности и некоторые банальности разжевываются уж слишком долго, но в целом для базового понимания сойдет (по ссылке есть и видео и pdf). Fogelя прав в том, что озвучил ( "План запроса читается снизу вверх" )Уже это хреновая формулировка независимо от того, что ты считаешь низом, а что верхом. План читается от первой листовой операции. Хотя надо сделать оговорку для скаляров в списке выборки. И то, это справедливо только для serial plans. Для parallel execution все несколько сложнее. Разбирать дальнейшую чушь нет смысла. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.10.2016, 23:33 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
FogelПлан запроса читается снизу вверх. Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. объяснишь? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.10.2016, 23:34 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
dbms_photoshopДля начинающих вот тетенька подробно объясняет Execution Plans - Learn by Example Добавлю к этому еще серию от Льюиса: Execution Plans: Part 1 Finding plans Execution Plans Part 2: Things to see Execution Plans Part 3: “The Rule” Execution Plans Part 4: Precision and Timing Execution Plans part 5: First Child Variations Execution Plans Part 6: Pushed Subqueries Execution Plans Part 7: Query Blocks and Inline Views Execution Plans Part 8: Cost, time, etc. Execution Plans Part 9: Multiplication Execution Plans Part 10: Guesswork Execution Plans Part 11: Actuals Execution Plans Part 12: Cardinality Feedback Execution Plans Part 13: SQL Trace Execution Plans Part 14: SQL Monitoring Порядок выполнения начинает описываться в 3-ей ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.10.2016, 23:45 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
dbms_photoshopПлан читается от корня, выполнения начинается от первой листовой операцииFixed. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 23.10.2016, 23:52 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
dbms_photoshopПлан читается от корня, выполнения начинается от первой листовой операции Немного не понятно, зачем читать от корня, если выполнять от первой листовой операции. Почему не: Execution plan выполняется от корня, доступ к данным начинается с первой листовой операции (с поправкой на различные scalar subquery, parallel execution etc, т.е. условный "типовой" план в вакууме). xtenderобъяснишь? rowsource execution statistics появится после того, как снизу вверх прочитают? Тогда на эту же тему и пример с конкатенацией (VW_ORE_% - OR-Expansion, 12.2): Код: plsql 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. Я смотрел все из вышеприведенных ссылок. У Jonathan Lewis есть каталог тут . По теме топика рекомендую разбор от Tanel Poder, т.к. там дается системный подход по тому, как проверять, что выполняется, порядок выполнения, а не свод правил (аля, first-child first и т.д.): http://enkitec.tv/2013/03/13/tanel-poders-hacking-session-how-oracle-sql-plans-are-really-executed-part-1/ http://enkitec.tv/2013/03/14/tanel-poders-hacking-session-how-oracle-sql-plans-are-really-executed-part-2/ ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.10.2016, 06:54 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
SeaGaterowsource execution statistics появится после того, как снизу вверх прочитают?не понял я к чему такой вопрос, если в моем примере rowsource execution statistics и так можно сказать просто прочитав план? SeaGateПо теме топика рекомендую разбор от Tanel Podeэтот конкретно не помню, но у него есть еще пара очень хороших статей: 1. http://blog.tanelpoder.com/2009/04/24/tracing-oracle-sql-plan-execution-with-dtrace/ 2. http://blog.tanelpoder.com/2008/06/15/advanced-oracle-troubleshooting-guide-part-6-understanding-oracle-execution-plans-with-os_explain/ и скрипт: http://blog.tanelpoder.com/files/scripts/tools/unix/os_explain собственно тут Танел и объясняет более конкретно с названиями этих процедур(но сложнее) то, что я говорил тут - 19813880 : xtenderКаждый шаг плана проще всего объяснять как некую процедуру, вложенные шаги которой являются операциями-процедурами, запускаемыми/останавливаемые этой процедурой и постепенно возвращающие в нее свои результаты ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.10.2016, 11:59 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
xtenderне понял я к чему такой вопрос, если в моем примере rowsource execution statistics и так можно сказать просто прочитав план? Это было просто предположение того, что будет, если план будет прочитан "снизу вверх" (что я трактую по plan_table.id как 2->1->0). xtenderи скрипт: http://blog.tanelpoder.com/files/scripts/tools/unix/os_explain Не вижу, каким прямым образом в задаче определения порядка выполнения операций плана выполнения поможет os_explain. Для этих целей предназначен http://blog.tanelpoder.com/files/scripts/dtrace/qer_trace.sh , т.к. с os_explain необходимо применять дополнительные телодвижения для получения pstack в нужный момент (во время выполнения запроса). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.10.2016, 12:34 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
SeaGateЭто было просто предположение того, что будет, если план будет прочитан "снизу вверх" (что я трактую по plan_table.id как 2->1->0).где предположение? Там только странный вопрос... SeaGateНе вижу, каким прямым образом в задаче определения порядка выполнения операций плана выполнения поможет os_explain.если внимательно посмотришь, то именно в этом скрипте у Танела маппинг реальных процедур к названиям операций плана и в первой ссылке даже показано как именно маппить. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.10.2016, 12:42 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
xtender, xtenderесли внимательно посмотришь, то именно в этом скрипте у Танела маппинг реальных процедур к названиям операций плана и в первой ссылке даже показано как именно маппить. Это я видел. qer_trace.sh позволит получать порядок вызова функций, предварительно запуская скрипт. Для os_explain сначала нужно получить pstack в момент выполнения. Если мне нужно гарантированно знать, что и как выполняется, я: 1. создаю сессию 2. запускаю qer_trace.sh 3. выполняю запрос 4. смотри результат С os_explain ты в какой момент предлагаешь pstack снимать для запроса как у ТС? Задача решаемая, но зачем лишние телодвижения, когда есть qer_trace.sh ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.10.2016, 12:46 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
SeaGateНемного не понятно, зачемВидя ограниченность первой формулировки решил ее поправить, но вторая получилась не лучше. На этом я решил остановиться, хотя вообще ничего не стоило писать. :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.10.2016, 12:50 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
SeaGate, еще раз... ты первую ссылку таки прочитал? там все и показано: Код: plsql 1. 2. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.10.2016, 12:55 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
xtender, xtenderеще раз... ты первую ссылку таки прочитал? там все и показано: dtrace -p 1063 -Fn 'pid$target:oracle:qer*Fetch*:entry pid$target:oracle:qer*Fetch*:return' | tee plan.txt sed -f os_explain.sed plan.txt Этого не заметил. Но это сложнее, чем Код: plsql 1. Мой пост в том, что для определения порядка выполнения rowsource функций проще использовать qer_trace.sh, а не то, что ты предлагаешь, как я тебя понял: dtrace + строка probes dtrace + tee? + sed? + os_explain.sed (? = опциональные). Ссылка http://blog.tanelpoder.com/files/scripts/tools/unix/os_explain на bash, sed оттуда получить не сложно (в его tpt_public скриптах я даже не вижу os_explain.sed . os_explain, qer_trace.sh есть), но зачем все эти манипуляции, когда есть qer_trace.sh . os_explain.sed разве что для "разыменовывания" функций сгодится в конкретной задаче, если в этом есть потребность. Однако в qer_trace.sh есть то, чего не делает os_explain: трассировка kcbgtcr с указанием файла, блока, функцией доступа из x$kcbwh . ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.10.2016, 15:26 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
SeaGate, что ж так разжевывать то все надо... qer_trace для понимания как выполняются строки плана(вопрос ТСа) избыточен, т.к. содержит еще пару лишних инструкций, и не дает связи между строками плана и названиями функций. Между тем dtrace -Fn 'pid$target:oracle:qer*Fetch*:entry pid$target:oracle:qer*Fetch*:return' + маппинг из os_explain(TRANSLATION_STRING) дают именно нужную информацию о порядке выполнения и вложенности. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 24.10.2016, 16:12 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
как оказывается сложно читать неотформатированные планы )) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 25.10.2016, 12:38 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
xtendermurr31, Код: plsql 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. Каждый шаг плана проще всего объяснять как некую процедуру, вложенные шаги которой являются операциями-процедурами, запускаемыми/останавливаемые этой процедурой и постепенно возвращающие в нее свои результаты. Т.е. в твоем плане это будет так: 0. Запускается SELECT, который запускает NESTED LOOPS из шага 1; 1. NESTED LOOPS шага 1, запускает NESTED LOOPS из шага 2 и по возвращенным строкам(ROWIDs) оттуда выполняет шаг 6, т.е. достает оттуда строки по найденным роуайди из шага 2; 2. NESTED LOOPS шага 2 запускает процедуру из шага 3 (TABLE ACCESS BY INDEX ROWID) и по возвращенным строкам оттуда выполняет шаг 5, т.е. фильтрует эти строки по INDEX UNIQUE SCAN индекса DEPT_ID_PK 3. Шаг 3 - TABLE ACCESS BY INDEX ROWID - запускает шаг 4(INDEX RANGE SCAN) и по возвращенным оттуда ROWID достает строки из EMPLOYEES 4. Шаг 4 сканирует индекс FIRST_NAME через IRS(index range scan) по предикату: access(UPPER("FIRST_NAME")='GUY') Насколько корректно выражение 'фильтрует' в п.2? В предикатах access ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.10.2016, 23:04 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
TygНасколько корректно выражение 'фильтрует' в п.2? В предикатах accessну, тут дело не в filter/access предикатах вообще, это я просто не вглядывался в сам запрос - реально тут должно быть наличие внешнего ключа и not null, и на самом деле никакого отсева, а просто добавление данных из departments. Кстати, projection по-хорошему надо тоже смотреть/показывать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 26.10.2016, 23:11 |
|
||
|
чтение плана запроса
|
|||
|---|---|---|---|
|
#18+
Tyg... Насколько корректно выражение 'фильтрует' в п.2? В предикатах access Имхо, смысл в этой фразе применительно конкретно к пункту 2 определенно есть. Формально соединение по условию в рел алгебре определяется как комбинация (последовательность) декартова произведения с последующей фильтрацией по условию. Соответственно здесь - строка, приезжающая на шаг 2 с шага 3 будет выброшена из процесса формирования результирующего набора, то есть, по существу, буквально отфильтрована , если скан индекса на шаге 5 окажется безрезультатным. Как минимум, мне представляется понятным, о чем речь при таком словоупотреблении. Хотя конкретный изображенный в плане алгоритм соединения может быть также вполне корректно быть изложен в других термина. Вот в пункте 1 подозревать отсутствие в таблице строки, rowid которой оказался найденным в индексе сложнее, и для п1 применение термина 'фильтрует' для конкретного запроса выглядит более искусственным. Но даже здесь - формально-логически - фильтрует, если исходить из чтения соединения как комбинации декартова произведения с наложение последующего фильтра ( в этом месте по условию равенства D.rowid для ведущего набора, полученного с шага 2 и ведомого, выбираемого на шаге 6) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 27.10.2016, 00:21 |
|
||
|
|

start [/forum/topic.php?fid=52&gotonew=1&tid=1887143]: |
0ms |
get settings: |
8ms |
get forum list: |
19ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
181ms |
get topic data: |
10ms |
get first new msg: |
5ms |
get forum data: |
2ms |
get page messages: |
72ms |
get tp. blocked users: |
1ms |
| others: | 205ms |
| total: | 509ms |

| 0 / 0 |
