#sql #oracle #execution
#sql #Oracle #выполнение
Вопрос:
EXPLAIN PLAN FOR
SELECT sightings.sighting_id, spotters.spotter_name,
sightings.sighting_date
FROM sightings
INNER JOIN spotters
ON sightings.spotter_id = spotters.spotter_id
WHERE sightings.spotter_id = 1255;
SELECT plan_table_output
FROM table(dbms_xplan.display('plan_table',null,'basic'));
id Operation Name
0 select statement
1 nested loops
2 table access by index rowid spotters
3 index unique scan pk_spotter_ID
4 table access full sightings
Я пытаюсь понять, что именно здесь происходит, правильно ли это звучит:
-
Сначала вычисляется оператор select, и атрибуты, отсутствующие в списке выбора, игнорируются для вывода
-
Затем вложенный цикл вычисляет внутреннее соединение для spotters.spotters_id = sightings.spotter_id
-
Доступ к таблице по индексу rowid извлекает строки с идентификаторами строк, которые были возвращены на шаге 3 из таблицы spotters
-
Проверка уникальности индекса, сканирует spotter_id в индексе PK_SPOTTER_ID и находит строки, связанные с идентификаторами строк в таблице spotters
-
Полный доступ к таблице, затем полностью просматривает наблюдения, пока не будет найден sighting_id = 1255
Комментарии:
1. Кажется, вы указали неправильный план выполнения
2. да, извините! я отредактировал его сейчас
3.Прочитайте план выполнения снизу вверх слева направо.
Id
столбец не указывает, что операция выполняется первой. Несмотря на то, что план выполнения представлен вам в виде списка (табличной) формы, на самом деле он имеет древовидную форму. итак, вы читаете это, начиная с листьев. сначала выполняется 1.Index unique scan
, затем 2.sightings table access full
3.spotters
осуществляется доступ по индексу rowid 4.nested loop
и, наконец, 5.select
узнайте больше
Ответ №1:
Шаги кажутся в основном правильными, но должны быть дополнены. Проекцию (выбор соответствующих столбцов) оптимально выполнять как можно раньше на этапе сканирования. Операция индексирования — это ПОИСК (вы не сканируете весь индекс)
Комментарии:
1. @01ldaniels, это отвечает на твой вопрос? Вам нужны какие-либо разъяснения?
Ответ №2:
ПРИМЕЧАНИЕ: ЭТОТ ОТВЕТ ОТНОСИТСЯ К ИСХОДНОЙ ВЕРСИИ ВОПРОСА.
Oracle считывает две таблицы целиком.
Это хеширование каждой из таблиц на основе join
ключей — «переупорядочивание» таблиц таким образом, чтобы похожие ключи появлялись рядом друг с другом.
Он выполняет объединение.
Затем он выполняет вычисления для окончательного select
и возвращает результаты пользователю.
Комментарии:
1. Только одна из таблиц хэшируется заранее. Выполняется потоковая передача другой таблицы.
2. @NicholasKrasnov, вопрос был впервые опубликован с неправильным планом выполнения, который содержал хэш-соединение.
3. @DuduMarkovitz Ах, я вижу, Op отредактировал вопрос после того, как был опубликован ответ… Я удалю свой предыдущий комментарий, несмотря на некорректное описание обработки хэш-соединения.
4. @NicholasKrasnov, вы можете видеть, что я уже прокомментировал обработку хэш-соединения.
Ответ №3:
Это то, что происходит, неофициально, в правильном порядке:
-- The index pk_spotter_id is scanned for at most one row that satisfies spotter_id = 1255
3 index unique scan pk_spotter_ID
-- The spotter_name column is fetched from the table spotters for the previously found row
2 table access by index rowid spotters
-- A nested loop is run for each (i.e. at most one) of the previously found rows
1 nested loops
-- That nested loop will scan the entire sightings table for rows that match the join
-- predicate sightings.spotter_id = spotters.spotter_id
4 table access full sightings
-- That'll be it for your select statement
0 select statement
В общем (есть множество исключений), планы выполнения Oracle можно прочитать
- Снизу вверх
- Первый брат сначала
Это означает, что вы спускаетесь по дереву, пока не найдете первую конечную операцию (например, # 3), которая будет выполнена «первой», ее результаты передаются родительскому элементу (например, # 2), затем все дочерние элементы выполняются сверху вниз, результаты всех дочерних элементов также передаются родительскому элементу, затем родительский результат передается большому родительскому элементу (например, # 1), пока вы не достигнете верхней операции.
Это очень неформальное объяснение того, что происходит. Обратите внимание, что будет много исключений из этих правил, как только инструкции станут более сложными.