Единственный второй верный ответ -
F. это неправильный дизайн, денормализующий CUSTOMER_NAME
в таблице orders
и противоречащий ему с нормальной формой .
Ответ C может быть правильным где-то во времена Oracle 8 (то есть 20 лет go), но теперь это окончательно неверно! .
Oracle вводит скалярное кеширование подзапроса событие по причине для ограничения количества выполнений подзапросов .
Вот простая демонстрация
Эта настройка в Oracle 19.2 имеет 10 000 заказов и 1 000 клиентов.
create table customers as
select rownum customer_id, 'cust_'||rownum customer_name from dual connect by level <= 1000;
create index customers_idx1 on customers (customer_id);
create table orders as
select rownum order_id, trunc(rownum/10)+1 customer_id, cast (null as varchar2(100)) customer_name
from dual connect by level <= 10000;
Обновление выполняется на 100 000 строк, как и ожидалось
UPDATE /*+ gather_plan_statistics */ orders o
SET customer_name = (
SELECT customer_name FROM customers WHERE customer_id=o.customer_id
);
Подсказка gather_plan_statistics
собирает статистику выполнения, которую мы рассмотрим.
SQL_ID 8r610vz9fknr6, child number 0
-------------------------------------
UPDATE /*+ gather_plan_statistics */ orders o SET customer_name = (
SELECT customer_name FROM customers WHERE customer_id=o.customer_id )
Plan hash value: 3416863305
--------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads |
--------------------------------------------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1 | | 0 |00:00:00.18 | 60863 | 21 |
| 1 | UPDATE | ORDERS | 1 | | 0 |00:00:00.18 | 60863 | 21 |
| 2 | TABLE ACCESS FULL | ORDERS | 1 | 10000 | 10000 |00:00:00.01 | 21 | 18 |
| 3 | TABLE ACCESS BY INDEX ROWID BATCHED| CUSTOMERS | 1001 | 1 | 1000 |00:00:00.01 | 2020 | 3 |
|* 4 | INDEX RANGE SCAN | CUSTOMERS_IDX1 | 1001 | 1 | 1000 |00:00:00.01 | 1020 | 3 |
--------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("CUSTOMER_ID"=:B1)
Информация об импатенте находится в столбце Start
, мы видим, что к таблице customers
обращались только 1001 раз, т.е. почти только один раз для клиента и не один раз для заказа,