план выполнения oracle, пытаюсь понять

#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
  

Я пытаюсь понять, что именно здесь происходит, правильно ли это звучит:

  1. Сначала вычисляется оператор select, и атрибуты, отсутствующие в списке выбора, игнорируются для вывода

  2. Затем вложенный цикл вычисляет внутреннее соединение для spotters.spotters_id = sightings.spotter_id

  3. Доступ к таблице по индексу rowid извлекает строки с идентификаторами строк, которые были возвращены на шаге 3 из таблицы spotters

  4. Проверка уникальности индекса, сканирует spotter_id в индексе PK_SPOTTER_ID и находит строки, связанные с идентификаторами строк в таблице spotters

  5. Полный доступ к таблице, затем полностью просматривает наблюдения, пока не будет найден 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), пока вы не достигнете верхней операции.

Это очень неформальное объяснение того, что происходит. Обратите внимание, что будет много исключений из этих правил, как только инструкции станут более сложными.