Почему oracle выбрал INDEX FULL SCAN, а затем ДОСТУП ПО INDEX ROWID против FULL TABLE SCAN? - PullRequest
1 голос
/ 05 января 2020

Почему oracle выбрал INDEX FULL SCAN, а затем ACCESS BY INDEX ROWID вместо простого сканирования таблицы, которое является одним шагом и делает то же самое и, вероятно, быстрее?

почему oracle выбирает

|   2 |   TABLE ACCESS BY INDEX ROWID
|   3 |    INDEX FULL SCAN    

over

|  2 |  TABLE ACCESS FULL| 

Для дальнейшего уточнения это запрос и полный план выполнения

SELECT EMP_NO, ENAME, SALARY, dname 
FROM EMP E, DEPT D
WHERE E.DEPT_NO=D.DEPT_NO;



Execution Plan
----------------------------------------------------------
Plan hash value: 2125045483

----------------------------------------------------------------------------------------
| Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |         |   879 | 35160 |     8  (13)| 00:00:01 |
|   1 |  MERGE JOIN                  |         |   879 | 35160 |     8  (13)| 00:00:01 |
|   2 |   TABLE ACCESS BY INDEX ROWID| DEPT    |     7 |    91 |     2   (0)| 00:00:01 |
|   3 |    INDEX FULL SCAN           | DEPT_PK |     7 |       |     1   (0)| 00:00:01 |
|*  4 |   SORT JOIN                  |         |   879 | 23733 |     6  (17)| 00:00:01 |
|   5 |    TABLE ACCESS FULL         | EMP     |   879 | 23733 |     5   (0)| 00:00:01 |
----------------------------------------------------------------------------------------

Ответы [ 2 ]

1 голос
/ 06 января 2020

Как правило, полное сканирование таблицы должно считываться до верхней отметки таблицы (ie почти каждый блок, который когда-либо был выделен в соответствии с таблицей). Если из таблицы произошло большое удаление, в таблице может быть 10 000 блоков, в основном пустых, которые он должен прочитать.

Индекс является более сложной структурой, но полное сканирование индекса не приходится иметь дело с пустыми блоками. Также индексы (так как они имеют только подмножество столбцов) имеют тенденцию быть меньше и, как правило, дольше хранятся в кэше.

В вашем примере общая стоимость доступа к индексу равна 3. и таблица из индекса. Это довольно низкий уровень, и, возможно, сканирование таблицы вышло на уровне 4 или 5 (тоже низкое, но все же второе).

0 голосов
/ 06 января 2020

Вы заметите, что оптимизатор делает выбор FULL TABLE SCAN в таблице EMP. Затем он использует ключ EMP.DEPT_NO для поиска подходящего значения в DEPT, потому что в этом случае выполнение поиска в 879 раз, по-видимому, быстрее (по крайней мере, по мнению оптимизатора), чем выполнение FULL TABLE SCAN для DEPT и выполнение 879 * 7 сравнений.

Для интереса вы можете проверить, как недавно статистика была собрана по этим таблицам, посмотрев на представления USER_TABLES или DBA_TABLES:

SELECT TABLE_NAME, LAST_ANALYZED
  FROM USER_TABLES
  WHERE TABLE_NAME IN ('EMP', 'DEPT')

И если вы хотите, вы можете собрать свободные sh Статистика в этих таблицах с использованием

BEGIN
  DBMS_STATS.GATHER_TABLE_STATISTICS(OWNNAME => 'your_schema_name',
                                     TABNAME => 'EMP',
                                     CASCADE => TRUE);

  DBMS_STATS.GATHER_TABLE_STATISTICS(OWNNAME => 'your_schema_name',
                                     TABNAME => 'DEPT',
                                     CASCADE => TRUE);
END;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...