SORT UNIQUE NOSORT
не занимает слишком много времени. Вы смотрите на оценки из плохих планов выполнения, которые, вероятно, являются результатом необоснованных параметров оптимизатора. Например, установка параметра OPTIMIZER_INDEX_COST_ADJ в 1 вместо 100 по умолчанию может создать аналогичный план. Скорее всего, ваш запрос выполняется медленно, потому что ваша база данных занята или просто медленна.
Что случилось с опубликованным планом выполнения?
Опубликованный план выполнения кажется необоснованным.Получение данных должно занимать гораздо больше времени, чем просто выкидывать дубликаты. И потребительская операция, SORT UNIQUE NOSORT
, может начаться почти в то же время, что и операция производителя, INDEX FULL SCAN
. Обычно они должны заканчиваться почти одновременно. В плане выполнения в вопросе отображается оптимизатор оценки. Снимок экрана, приведенный ниже активного отчета, показывает фактические временные рамки для очень похожего запроса. Все шаги начинаются и останавливаются почти одновременно.
установка образца с разумным планом
Ниже приведена очень аналогичные установки, но с очень простой конфигурацией. Такое же количество строк читается (115 миллионов) и возвращается (1), и почти точно такой же размер сегмента (329 МБ против 331 МБ). План показывает почти все время, потраченное на INDEX FULL SCAN
.
drop table test1 purge;
create table test1(a number not null, b number, c number) nologging;
begin
for i in 1 .. 115 loop
insert /*+ append */ into test1 select 1, level, level
from dual connect by level <= 1000000;
commit;
end loop;
end;
/
create index test1_idx on test1(a);
begin
dbms_stats.gather_table_stats(user, 'TEST1');
end;
/
explain plan for select /*+ index(test1) */ distinct a from test1;
select * from table(dbms_xplan.display);
Plan hash value: 77032494
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 244K (4)| 00:48:50 |
| 1 | SORT UNIQUE NOSORT| | 1 | 3 | 244K (4)| 00:48:50 |
| 2 | INDEX FULL SCAN | TEST1_IDX | 115M| 329M| 237K (1)| 00:47:30 |
--------------------------------------------------------------------------------
Воссоздание плохой план
--Set optimizer_index_cost_adj to a ridiculously low value.
--This changes the INDEX FULL SCAN estimate from 47 minutes to 29 seconds.
alter session set optimizer_index_cost_adj = 1;
--Changing the CPUSPEEDNW to 800 will exactly re-create the time estimate
--for SORT UNIQUE NOSORT. This value is not ridiculous, and it is not
--something you should normally change. But it does imply your CPUs are
--slow. My 2+ year-old desktop had an original score of 1720.
begin
dbms_stats.set_system_stats('CPUSPEEDNW', 800);
end;
/
explain plan for select /*+ index(test1) */ distinct a from test1;
select * from table(dbms_xplan.display);
Plan hash value: 77032494
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 16842 (86)| 00:03:23 |
| 1 | SORT UNIQUE NOSORT| | 1 | 3 | 16842 (86)| 00:03:23 |
| 2 | INDEX FULL SCAN | TEST1_IDX | 115M| 329M| 2389 (2)| 00:00:29 |
--------------------------------------------------------------------------------
Как исследовать
Проверьте параметры.
select name, value from v$parameter where name like 'optimizer_index%'
NAME VALUE
---- -----
optimizer_index_cost_adj 1
optimizer_index_caching 0
Также проверьте статистику системы.
select * from sys.aux_stats$;
+---------------+------------+-------+------------------+
| SNAME | PNAME | PVAL1 | PVAL2 |
+---------------+------------+-------+------------------+
| SYSSTATS_INFO | STATUS | | COMPLETED |
| SYSSTATS_INFO | DSTART | | 09-23-2013 17:52 |
| SYSSTATS_INFO | DSTOP | | 09-23-2013 17:52 |
| SYSSTATS_INFO | FLAGS | 1 | |
| SYSSTATS_MAIN | CPUSPEEDNW | 800 | |
| SYSSTATS_MAIN | IOSEEKTIM | 10 | |
| SYSSTATS_MAIN | IOTFRSPEED | 4096 | |
| SYSSTATS_MAIN | SREADTIM | | |
| SYSSTATS_MAIN | MREADTIM | | |
| SYSSTATS_MAIN | CPUSPEED | | |
| SYSSTATS_MAIN | MBRC | | |
| SYSSTATS_MAIN | MAXTHR | | |
| SYSSTATS_MAIN | SLAVETHR | | |
+---------------+------------+-------+------------------+
Чтобы узнать, где действительно потрачено время, используйте инструмент, например, активный отчет.
select dbms_sqltune.report_sql_monitor(sql_id => '5s63uf4au6hcm',
type => 'active') from dual;
Версия Orcale: Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production – Comencau