Эффективное использование индекса для самостоятельного присоединения к группе

Я пытаюсь ускорить следующее

create table tab2 parallel 24 nologging compress for query high as
select /*+ parallel(24) index(a ix_1) index(b ix_2)*/ 
       a.usr
       ,a.dtnum
       ,a.company
       ,count(distinct b.usr) as num
       ,count(distinct case when b.checked_1 = 1 then b.usr end) as num_che_1
       ,count(distinct case when b.checked_2 = 1 then b.usr end) as num_che_2
from tab a
join tab b on a.company = b.company
              and b.dtnum between a.dtnum-1 and a.dtnum-0.0000000001                 
group by a.usr, a.dtnum, a.company;

с помощью индексов

create index ix_1 on tab(usr, dtnum, company);
create index ix_2 on tab(usr, company, dtnum, checked_1, checked_2);

но план выполнения говорит мне, что это будет полное сканирование обоих индексов, и вычисления очень долгие (1 день недостаточно).

О данных. Вкладка «Таблица» содержит более 3 млн записей. Ни один из отдельных столбцов не уникален. Уникальными значениями здесь являются пары (usr, dtnum), где dtnum — это дата со временем, записанная в виде числа в формате yyyy,mmddhh24miss. Столбцы checked_1, checked_2 имеют значения из набора (null, 0, 1, 2). Компания имеет идентификатор компании. Каждая пара может иметь только одно значение checked_1, checked_2 и company, так как она уникальна. Каждый пользователь может быть в нескольких парах с разными dtnum.

Изменить

@Roberto Hernandez: Я прикрепил картинку с планом казни. Что касается параллельного 24, в нашей компании нам говорят создавать таблицы с параметрами «параллельный [число] без логирования сжимать для запроса высокого». Я использую 24, но я не эксперт в этой области.

введите здесь описание изображения

@Саян Малакшинов: http://sqlfiddle.com/#!4/40b6b/2 Здесь я упростил, указав данные с checked_1 = checked_2, но в реальной жизни это может быть не так.

@scaisEdge: для

create index my_id1 on tab (company, dtnum);
create index my_id2 on tab (company, dtnum, usr);

Я получаю введите здесь описание изображения введите здесь описание изображения


person stolikp    schedule 18.07.2020    source источник
comment
Предоставьте ваши образцы данных, пожалуйста   -  person Sayan Malakshinov    schedule 18.07.2020
comment
можете ли вы предоставить план объяснения исходного запроса   -  person Roberto Hernandez    schedule 18.07.2020
comment
почему параллель 24? где вы берете этот номер? почему бы не позволить Oracle решить, какая степень является лучшей?   -  person Roberto Hernandez    schedule 18.07.2020


Ответы (2)


Для таблицы tab ваше условие соединения основано на столбцах

company, datun 

поэтому вы должны индексировать в первую очередь на основе этих столбцов

create index my_id1 on tab (company, datum);

Используемые вами индексы бесполезны, потому что они не содержат крайних левых столбцов позиции, используйте условие ij join/where

В конце концов вы можете добавить право пользователя на большинство вариантов, чтобы избежать необходимости доступа к таблице, и позволить механизму БД извлекать всю информацию внутри значений индекса.

 create index my_id1 on tab (company, datum, user, checked_1, checked_2);
person scaisEdge    schedule 18.07.2020
comment
Смотрите планы выполнения в редактировании моего вопроса. Эти индексы выглядят не очень хорошо. - person stolikp; 18.07.2020
comment
@stolikp, тогда у вас не так много шансов улучшить производительность ... .. в любом случае ответ обновлен, добавив избыточность alos cof checked_1 _2 - person scaisEdge; 18.07.2020
comment
ХОРОШО. Обновленный ответ ничем не отличается от того, что я сделал. Схема выполнения такая же, как и на первой картинке. - person stolikp; 18.07.2020
comment
Сколько уникальных значений в Company и datum ? Вы пытались использовать индексы растровых изображений, а не индексы B-Tree? - person Atif; 18.07.2020
comment
Отдельные компании: 16 847, отдельные dtnums: 2 775 994, все строки: 3 366 074. Должен ли я попробовать растровый индекс с ними? Если да, то на каких столбцах? - person stolikp; 18.07.2020

Индексы (растровые или иные) не так полезны для этого выполнения. Если вы посмотрите на план выполнения, оптимизатор полагает, что группировка сократит вывод до 1 строки. Это приводит к сериализации (PX SELECTOR). Поэтому я бы поставил под сомнение качество вашей статистики. Что вам может понадобиться, так это создать группу столбцов из трех столбцов group-by, чтобы улучшить оценку кардинальности группы.

person BobC    schedule 18.07.2020
comment
Не уверен, правильно ли я понимаю. Вы говорите, что я должен использовать группировку по трем столбцам? То есть группировать наборы группировки((a.usr, a.dtnum, a.company))? Это не изменило того факта, что PX SELECTOR находится в плане выполнения, а результирующая кардинальность прогнозируется как 1. Более того, я попробовал «АНАЛИЗИРОВАТЬ ТАБЛИЦУ на вкладке ВЫЧИСЛИТЬ СТАТИСТИКУ», но никаких изменений в плане выполнения после нового анализа. - person stolikp; 19.07.2020
comment
1. Посмотрите на план объяснения - оценочная кардинальность группы равна 1. Мне это подозрительно - но вы знаете свои данные; это правильно? Если нет, то 2. Предлагаю создать группу столбцов (ничего общего с наборами группировки). См. документ для DBMS_STATS.CREATE_EXTENDED_STATS. 3. Наконец, команда ANALYZE уже около десяти лет не рекомендуется для сбора статистики. Вы должны использовать DBMS_STATS.GATHER_TABLE_STATS. И вы должны сделать это после создания группы столбцов в 2 выше, убедившись, что собрали гистограмму в группе столбцов. - person BobC; 22.07.2020