Не так давно я опубликовал заметку о некотором варианте иерархического запроса, который выполняется очень долго (почти неограниченно) и не потребляет иных ресурсов базы данных кроме CPU.
Возникла довольно естественная идея использовать этот метод для сопоставления CPU интенсивных задач в БД Oracle. Например, если мы встраиваем такую прожорливую CPU-функцию в наш пайплайн исполнения SQL-запроса так, чтобы она выполнилась более миллиарда раз, то получаем возможность сравнить затраты на CPU в разных случаях.
В данном случае мы будем сравнивать по производительности различные функции хеширования в Oracle: ORA_HASH и различные варианты STANDARD_HASH.
Мы выполняем запросы следующего вида:
Baseline не выполняет доп. функций на CPU:
select * from (select distinct id
from (select 'abcdef' id from dual
union all
select 'fgrjk' from dual)
connect by level <= 3e1);
Запрос с ORA_HASH:
select * from (select distinct ora_hash(id,1111113)
from (select 'abcdef' id from dual
union all
select 'fgrjk' from dual)
connect by level <= 3e1);
Запрос с вычислением хеша одним из стандартных методов:
select * from (select distinct STANDARD_HASH(id,'SHA384')
from (select 'abcdef' id from dual
union all
select 'fgrjk' from dual)
connect by level <= 3e1);
Метод |
Время исполнения (сек) |
Разница с baseline на (%) |
Baseline |
773 |
0% |
ORA_HASH |
959 |
24.0% |
MD5 |
1462 |
87.5% |
SHA1 |
2536 |
228% |
SHA256 |
5019 |
549% |
SHA512 |
5061 |
554% |
Типичный SQL Monitor-отчёт для подобных запросов:
SQL Monitoring Report
SQL Text
select * from (select distinct STANDARD_HASH(id,'SHA256') from (select 'abcdef' id from dual union all select 'fgrjk' from dual) connect by level <= 3e1)
Global Information
Status : DONE (ALL ROWS)
Instance ID : 2
Session : REMIZOV (509:24232)
SQL ID : fwhbynu8jtfr3
SQL Execution ID : 33554432
Execution Started : 07/16/2024 10:11:47
First Refresh Time : 07/16/2024 10:11:53
Last Refresh Time : 07/16/2024 11:35:26
Duration : 5019s
Module/Action : PL/SQL Developer/SQL Window
Service : ZZZZZZ
Program : plsqldev.exe
Fetch Calls : 1
Global Stats
| Elapsed | Cpu | Other | Fetch |
| Time(s) | Time(s) | Waits(s) | Calls |
| 5019 | 4964 | 55 | 1 |
SQL Plan Monitoring Details (Plan Hash Value=682020348)
| Id | Operation | Name | Rows | Cost | Time | Start | Execs | Rows | Mem | Activity | Activity Detail |
| | | | (Estim) | | Active(s) | Active | | (Actual) | (Max) | (%) | (# samples) |
| 0 | SELECT STATEMENT | | | | 1 | +5019 | 1 | 2 | . | | |
| 1 | VIEW | | 2 | 5 | 1 | +5019 | 1 | 2 | . | | |
| 2 | HASH UNIQUE | | 2 | 5 | 5020 | +0 | 1 | 2 | 507KB | 86.30 | Cpu (4327) |
| 3 | CONNECT BY WITHOUT FILTERING (UNIQUE) | | | | 5014 | +6 | 1 | 2G | 2048 | 13.70 | Cpu (687) |
| 4 | VIEW | | 2 | 4 | 1 | +6 | 1 | 2 | . | | |
| 5 | UNION-ALL | | | | 1 | +6 | 1 | 2 | . | | |
| 6 | FAST DUAL | | 1 | 2 | 1 | +6 | 1 | 1 | . | | |
| 7 | FAST DUAL | | 1 | 2 | 1 | +6 | 1 | 1 | . | | |
=======================================================================================================================================================
Выводы
Вычисление хеша методом MD5 в 3.5 раза более затратно, чем ORA_HASH, а также даёт добавку порядка 87% к общему времени выполнения запроса (baseline), что совсем неплохо.
Остальные методы вычисления стандартного хеша гораздо затратнее.