powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Area в SGA, в которой выполняется nested loops
11 сообщений из 11, страница 1 из 1
Area в SGA, в которой выполняется nested loops
    #39956704
beginner2020
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.

В документации наткнулся на такой момент:
A sort merge has the same advantage over a nested loops join as the hash join: the database accesses rows in the PGA rather than the SGA, reducing logical I/O by avoiding the necessity of repeatedly latching and reading blocks in the database buffer cache. In general, hash joins perform better than sort merge joins because sorting is expensive. However, sort merge joins offer the following advantages over a hash join



Для обоих случаев dedicated и shared подключения, в какой именно area в SGA выполняется nested loops и всегда ли он выполняется в SGA?
Честно, гуглил и книжки Льюиса и Антонини шерстил - ответ не нашел(или не увидел).
...
Рейтинг: 0 / 0
Area в SGA, в которой выполняется nested loops
    #39956709
PuM256
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
beginner2020,

Для nested loops не нужны ни сортировки, ни хэширование, поэтому PGA не используется.
Во время выполнения каждый ряд первой таблицы сравнивается с каждым рядом второй таблицы по условию соединения. Если условие выполняется - возвращаем полученный ряд. Дополнительная память для этого не нужна. Записи получаем обычным гетом из буферного кэша.
...
Рейтинг: 0 / 0
Area в SGA, в которой выполняется nested loops
    #39956745
Фотография AlexFF__|
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
beginner2020
... в какой именно area в SGA выполняется nested loops и всегда ли он выполняется в SGA...

Данные же нужно откуда-то читать?
Из buffer_cache, он в SGA.

PuM256

Для nested loops не нужны ни сортировки, ни хэширование, поэтому PGA не используется...

Никогда не слышал о batching NLJ?
Довольно таки старая вещь.
...
Рейтинг: 0 / 0
Area в SGA, в которой выполняется nested loops
    #39956769
Melkomyagkii_newbi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PuM256
beginner2020,

Для nested loops не нужны ни сортировки, ни хэширование, поэтому PGA не используется.
Во время выполнения каждый ряд первой таблицы сравнивается с каждым рядом второй таблицы по условию соединения. Если условие выполняется - возвращаем полученный ряд. Дополнительная память для этого не нужна. Записи получаем обычным гетом из буферного кэша.


гетом получили, куда? а если джойним с набором который нужно предварительно посортировать?
...
Рейтинг: 0 / 0
Area в SGA, в которой выполняется nested loops
    #39956937
Alexander Anokhin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
beginner2020


В документации наткнулся на такой момент:
A sort merge has the same advantage over a nested loops join as the hash join: the database accesses rows in the PGA rather than the SGA, reducing logical I/O by avoiding the necessity of repeatedly latching and reading blocks in the database buffer cache. In general, hash joins perform better than sort merge joins because sorting is expensive. However, sort merge joins offer the following advantages over a hash join



Я посмотрел где это пишут, там ещё пишут
https://docs.oracle.com/database/121/TGSQL/tgsql_join.htm#TGSQL94690 A sort merge join is a variation on a nested loops join.
нормально.


авторДля обоих случаев dedicated и shared подключения, в какой именно area в SGA выполняется nested loops и всегда ли он выполняется в SGA?

Некоторым операциям плана выполнения таким как HASH JOIN, SORT JOIN, SORT ORDER BY, SORT/HASH UNIQUE, BUFFER SORT (который ничего не сортирует кстати) и т.д. надо получить весь набор данных из подчинённого источника, и произвести какие-то действия (скажем отсортировать), прежде чем начать возвращать строки. Для этого выделяется в PGA области называются SQL Workarea (v$sql_worarea, v$sql_worarea_active, и т.д.), где могут храниться данные больших объёмов. Nested Loops не хранит таких объёмов.


Работает это так.
Предположим есть простой запрос и план выполнения
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
select * from t1;

------------------------------------------
| Id  | Operation                 | Name |
------------------------------------------
|   0 | SELECT STATEMENT          |      |
|   1 |  TABLE ACCESS STORAGE FULL| T1   |
------------------------------------------


Здесь шаг 0 SELECT STATEMENT вызывает шаг 1 TABLE ACCESS STORAGE FULL чтобы получить строки. Шаг 1 начинает сканировать таблицу, возвращает строки по одной и так пока не набирается количество строк равное fetch size (то что в SQL*Plus называется arraysize). Как только набралось, шаг 0 упаковывает результат, отправляет клиенту и ждёт следующий fetch call от клиента. Приходит следующий fetch и всё повторяется с того места где в прошлый раз остановились. Каждый fetch call таблица будет просканирована всё дальше.

Теперь предположим у нас есть сортировка
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
select * from t1 order by n;

-------------------------------------------
| Id  | Operation                  | Name |
-------------------------------------------
|   0 | SELECT STATEMENT           |      |
|   1 |  SORT ORDER BY             |      |
|   2 |   TABLE ACCESS STORAGE FULL| T1   |
-------------------------------------------


В этом случае шаг 0 вызовет шаг 1, тот вызовет шаг 2, получит все строки из шага 2 в SQL workarea, отсортирует, затем вернёт в шаг 0 количество строк равное fetch size, и каждый следующий fetch call будет возвращать строки из SQL workarea. Поэтому в этом случае первый fetch будет медленный, а остальные относительно быстрые, поскольку таблица уже не сканируется.
Шаг SORT ORDER BY блокирующий, он должен полностью выполниться перед тем как он сможет возвращать строки.


Теперь если у нас Nested Loops
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
select * from t1, t2 where t1.n = t2.n;

-------------------------------------------
| Id  | Operation                  | Name |
-------------------------------------------
|   0 | SELECT STATEMENT           |      |
|   1 |  NESTED LOOPS              |      |
|   2 |   TABLE ACCESS STORAGE FULL| T1   |
|*  3 |   INDEX RANGE SCAN         | I2   |
-------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   3 - access("T1"."N"="T2"."N")


Примерно тоже самое как в первом случае без блокирующих операций. Шаг 0 вызывает шаг 1, шаг 1 вызывает шаг 2, тот возвращает строку в шаг 1, шаг 1 вызывает шаг 3, тот сканирует индекс для данной строки, возвращает строки в шаг 1, тот возвращённые строки возвращает в шаг 0 и так пока не наберётся количество строк равное fetch size. Каждый следующий fetch call продожаем с того места где закончили.


В случае Hash Join
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
-------------------------------------------
| Id  | Operation                  | Name |
-------------------------------------------
|   0 | SELECT STATEMENT           |      |
|*  1 |  HASH JOIN                 |      |
|   2 |   TABLE ACCESS STORAGE FULL| T1   |
|   3 |   TABLE ACCESS STORAGE FULL| T2   |
-------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("T1"."N"="T2"."N")


Шаг 1 вызывает шаг 2, вытягивает все строки из таблицы строит на основе этого hash table, результат хранит в SQL workarea. Когда построил, шаг 1 вызывает шаг 3, для каждой строки из шага 3 ищет строки в hash table, найденные возвращает. Здесь построение hash table это блокирующая операция, которая должна полностью закончиться прежде чем HASH JOIN сможет возвращать строки. Шаг 2 выполняется один раз во время первого fetch call. Шаг 3 будет выполняться по немногу каждый следующий fetch call.


Начиная с 12с строки передаются между операциями не по одной, а пачками, если параметр _rowsets_enabled=true (default).

Дай знать, если что не ясно.
...
Рейтинг: 0 / 0
Area в SGA, в которой выполняется nested loops
    #39956961
beginner2020
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Это все ясно и огромное спасибо за то, что вообще время свое тратите на такие подробные ответы. Я об этом всем читал в Troubleshooting Oracle Performance by Christian Antognini.

НО,
Alexander Anokhin


Теперь если у нас Nested Loops
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
select * from t1, t2 where t1.n = t2.n;

-------------------------------------------
| Id  | Operation                  | Name |
-------------------------------------------
|   0 | SELECT STATEMENT           |      |
|   1 |  NESTED LOOPS              |      |
|   2 |   TABLE ACCESS STORAGE FULL| T1   |
|*  3 |   INDEX RANGE SCAN         | I2   |
-------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   3 - access("T1"."N"="T2"."N")


Примерно тоже самое как в первом случае без блокирующих операций. Шаг 0 вызывает шаг 1, шаг 1 вызывает шаг 2, тот возвращает строку в шаг 1, шаг 1 вызывает шаг 3, тот сканирует индекс для данной строки, возвращает строки в шаг 1, тот возвращённые строки возвращает в шаг 0 и так пока не наберётся количество строк равное fetch size. Каждый следующий fetch call продожаем с того места где закончили.


выходит, loop этот выполняется в памяти процесса(или треда) ассоциированного с сессией, т.е. результат(строка или все таки целый блок?) возвращаемый шагом 2 сохраняется где-то в PGA до последующего сканирования индекса?
...
Рейтинг: 0 / 0
Area в SGA, в которой выполняется nested loops
    #39956982
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
beginner2020
т.е. результат(строка или все таки целый блок?) возвращаемый шагом 2 сохраняется где-то в PGA до последующего сканирования индекса?

Тут важно понимать что есть "результат".
Пусть внешний источник данных содержит 1e6... не, мало - лучше 1e26 строк.
NL на это плевать он просто отбирает внешним циклом удобный набор строк (изначально 1 строка, с 12с - небольшой пакет строк).
Затем для каждой отобранной строки запускает внутренний цикл.
Таким образом, требуемый объем памяти невелик и не зависит от размера datasource 1.

HJ поступит совершенно иначе.
1. он будет упорно чтить datasource1 и строить хеш-таблицу в памяти, выжирая PGA.
1.1. когда памяти не хватит - начнет сбрасывать хеш-корзинки к TEMP.
2. и лишь вычитав datasource1 "до донышка" (и материализовав результат) возьмется за datasource2


С SMJ забавнее. Сам по себе он, как и NL, памяти практически не требует.
Однако требует на входе сортированных наборов.
И если конкретные наборы можно достать из БД уже правильно отсортированными (за счет access path) - то это отличный алгоритм для соединения больших объемов с вычислительной стоимостью близкой к линейной.
Однако так случается довольно редко - и тут появляется сортировка входных наборов со всеми вытекающими (возникает необходимость полностью вычитать оба набора в память/свалить в ТЕМП, отсортировать и лишь затем выполнить соединение) - и это уже сильно дороже.
...
Рейтинг: 0 / 0
Area в SGA, в которой выполняется nested loops
    #39956984
Alexander Anokhin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
beginner2020
выходит, loop этот выполняется в памяти процесса(или треда) ассоциированного с сессией, т.е. результат(строка или все таки целый блок?) возвращаемый шагом 2 сохраняется где-то в PGA до последующего сканирования индекса?

В SGA хранится то что может понадобиться многим процессам. В случае же shared servers каждый следующий fetch вызов может прилететь к разным процессам, поэтому SQL workareas, которые должны продолжать существовать между этими вызовыми fetch, надо хранить в SGA. Также надо хранить bind переменные, всякие дополнительные параметры, например, где закончился предыдущий fetch. Это актуально для запросов, но не для DML/DDL, где всё внутри одного процесса как в dedicated режиме.

Строки же, которые операции плана выполнения передают друг другу внутри одного вызова это временная информаыия как локальные переменные или параметры функций, которая никакому другому процессу не понадобятся и не должны быть видны, поэтому хранятся, очевидно, в памяти процесса, то что называется UGA (User Global Area).
...
Рейтинг: 0 / 0
Area в SGA, в которой выполняется nested loops
    #39956991
Alexander Anokhin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
beginner2020
результат(строка или все таки целый блок?)


Блоки обрабатываются операциями доступа к данным (как table full scan, index range scan, и т.д.), они достают и возвращают строки.
...
Рейтинг: 0 / 0
Area в SGA, в которой выполняется nested loops
    #39956994
Фотография andrey_anonymous
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexander Anokhin
очевидно, в памяти процесса, то что называется UGA (User Global Area).

Мнэээ... Александр, Вы, вероятно, опечатались.
AFAIR, в случае shared server именно UGA уезжает из PGA в Large Pool
...
Рейтинг: 0 / 0
Area в SGA, в которой выполняется nested loops
    #39956996
Alexander Anokhin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
andrey_anonymous
Alexander Anokhin
очевидно, в памяти процесса, то что называется UGA (User Global Area).

Мнэээ... Александр, Вы, вероятно, опечатались.
AFAIR, в случае shared server именно UGA уезжает из PGA в Large Pool

Точняк. CGA значит.
...
Рейтинг: 0 / 0
11 сообщений из 11, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Area в SGA, в которой выполняется nested loops
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]