Почему% ЦП и стоимость увеличиваются для этого плана выполнения? - PullRequest
1 голос
/ 24 апреля 2020

У меня есть таблица, которая заполнена множеством строк записей. Я объясняю и отображаю план выполнения до создания индекса для запроса

explain plan for
SELECT l_partKey, count(*)
FROM LINEITEM
GROUP BY L_PARTKEY
HAVING COUNT(l_tax) > 2;

SELECT * FROM table(dbms_xplan.display);

И это вывод

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2487493660

--------------------------------------------------------------------------------
| Id  | Operation           | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |          |  3023 | 15115 |  8821   (1)| 00:00:01 |
|*  1 |  FILTER             |          |       |       |            |          |
|   2 |   HASH GROUP BY     |          |  3023 | 15115 |  8821   (1)| 00:00:01 |
|   3 |    TABLE ACCESS FULL| LINEITEM |  1800K|  8789K|  8775   (1)| 00:00:01 |
--------------------------------------------------------------------------------

Затем я создаю этот индекс:

CREATE INDEX lineItemIdx ON LINEITEM(l_partKey);

Объясните и снова отобразите план выполнения, и это вывод:

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 573468153
--------------------------------------------------------------------------------
------

| Id  | Operation              | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |             |  3023 | 15115 |  1130   (5)| 00:00:01 |
|*  1 |  FILTER                |             |       |       |            |          |
|   2 |   HASH GROUP BY        |             |  3023 | 15115 |  1130   (5)| 00:00:01 |
|   3 |    INDEX FAST FULL SCAN| LINEITEMIDX |  1800K|  8789K|  1084   (1)| 00:00:01 |

Кто-нибудь знает, почему% cpu изменяется с 1, 1, 1 до 5, 5, 1?

После этого я удалил созданный мной индекс и создал новый индекс для l_partKey, l_tax, объяснил и снова отобразил выполнение:

CREATE INDEX lineItemIdx ON LINEITEM(l_partKey, l_tax);


PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------
Plan hash value: 573468153

--------------------------------------------------------------------------------
------

| Id  | Operation              | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |             |  3023 | 15115 |  1326   (4)| 00:00:01 |
|*  1 |  FILTER                |             |       |       |            |          |
|   2 |   HASH GROUP BY        |             |  3023 | 15115 |  1326   (4)| 00:00:01 |
|   3 |    INDEX FAST FULL SCAN| LINEITEMIDX |  1800K|  8789K|  1281   (1)| 00:00:01 |

Теперь наблюдается небольшое увеличение стоимости с 1130, 1130, С 1084 по 1326, 1326, 1281, при использовании нового индекса l_partKey, l_tax по сравнению с предыдущим индексом, который я создал. Почему это так? Разве этот индекс не должен увеличивать скорость обработки запросов больше, чем предыдущий индекс?

1 Ответ

1 голос
/ 24 апреля 2020

Ваш запрос требует подсчета всех строк в таблице 1,8 мегароу. Таким образом, Oracle должен выполнить какое-то полное сканирование, чтобы удовлетворить его.

Без полезного индекса необходимо полное сканирование таблицы: необходимо прочитать всю таблицу. Это, вероятно, хлопает операциями ввода-вывода сервера; поэтому процессор активен в течение небольшого процента прошедшего времени запроса. СУБД имеют две вещи, которые замедляют их. IO (чтение всей таблицы с диска) и CPU (вычисления). Без индекса центральный процессор тратит большую часть времени ожидания запроса на диске, чтобы доставить содержимое всей таблицы. Таким образом, процессор активен в течение меньшего процента прошедшего времени. С индексом диск должен доставлять меньше данных. Таким образом, процессор занимает больший процент от общего времени. CPU% не является хорошим показателем общей стоимости запросов.

Когда вы добавили свой первый индекс, вы сократили количество операций ввода-вывода, необходимых для удовлетворения запроса, поэтому процессор стал активным в течение большего процента прошедшего времени.

Ваш второй индекс привел к тому, что ваш запрос стоил почти точно так же, как ваш первый. Индексные элементы немного больше, поэтому Oracle должно сделать немного больше работы для их обработки; это может объяснить небольшое увеличение стоимости.

Не забывайте: Oracle - 43 года и версия 19. Поколения программистов работали над его оптимизацией. Попытка угадать «почему» для небольшой разницы в стоимости, вероятно, не стоит ваших проблем.

Наконец, в вашем запросе есть что-то странное. Вы делаете SELECT ... COUNT(*), а затем HAVING COUNT(column) > 2. COUNT(column) отличается от COUNT(*): первый подсчитывает ненулевые записи в column, где COUNT(*) подсчитывает их все. Это твое намерение?

В обоих запросах с индексами используется INDEX FAST FULL SCAN. Это святой Грааль полного сканирования. Ваш второй индекс включает ваш столбец l_tax, поэтому можно предположить, что он объявлен как NOT NULL, или он может не подходить для быстрого сканирования. В этом случае Oracle знает, что COUNT(*) совпадает с COUNT(l_tax). Вот почему оба индекса имеют один и тот же план, даже с небольшими расходами на этапы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...