Информация об изменениях

Сообщение [ora] оптимизация от 03.04.2025 14:33

Изменено 03.04.2025 14:34 Funny Rabbit

[ora] оптимизация
select s.sale_id,
s.costumer_id,
s.retailer_id,
p.product_name,
pct.product_category_name
from sales s,
products p,
product_categories pct
where p.product_id = s.product_id
and pct.product_category_id = p.product_category_id
and pct.product_category_name not in ('GROCERIES', 'CLOTHES')
and s.sale_dt >= trunc(add_months(sysdate, -6), 'mm');

Запрос объединяет информацию о продажах за последние полгода и работает медленно.
На основании данных отчёта sql-мониторинга и информации ниже нужно понять, на каких этапах висит запрос. Какие действия можно предпринять, чтобы его ускорить, не меняя при этом текст запроса?



Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

1 — SEL$1
5 — SEL$1 / S@SEL$1
6 — SEL$1 / P@SEL$1
7 — SEL$1 / PCT@SEL$1
8 — SEL$1 / PCT@SEL$1

Outline Data
-------------

/*+
BEGIN_OUTLINE_DATA
NLJ_BATCHING(@"SEL$1" "PCT"@"SEL$1")
USE_NL(@"SEL$1" "PCT"@"SEL$1")
USE_NL(@"SEL$1" "P"@"SEL$1")
LEADING(@"SEL$1" "S"@"SEL$1" "P"@"SEL$1" "PCT"@"SEL$1")
INDEX(@"SEL$1" "PCT"@"SEL$1" ("PRODUCT_CATEGORIES"."PRODUCT_CATEGORY_ID"))
FULL(@"SEL$1" "P"@"SEL$1")
FULL(@"SEL$1" "S"@"SEL$1")
OUTLINE_LEAF(@"SEL$1")
ALL_ROWS
DB_VERSION('12.2.0.1')
OPTIMIZER_FEATURES_ENABLE('12.2.0.1')
IGNORE_OPTIM_EMBEDDED_HINTS
END_OUTLINE_DATA
*/

Predicate Information (identified by operation id):
---------------------------------------------------

5 — filter("S"."SALE_DT">=TRUNC(ADD_MONTHS(SYSDATE@!,(-6)),'fmmm'))
6 — filter("P"."PRODUCT_ID"="S"."PRODUCT_ID")
7 — access("PCT"."PRODUCT_CATEGORY_ID"="P"."PRODUCT_CATEGORY_ID")
8 — filter("PCT"."PRODUCT_CATEGORY_NAME"<>'GROCERIES' AND "PCT"."PRODUCT_CATEGORY_NAME"<>'CLOTHES')


Я решил так: Создать индексы по product_category_name и s.sale_dt как trunc(sysdate) и партиционировать таблицу sales по полю sale_dt
[ora] оптимизация
select s.sale_id,
s.costumer_id,
s.retailer_id,
p.product_name,
pct.product_category_name
from sales s,
products p,
product_categories pct
where p.product_id = s.product_id
and pct.product_category_id = p.product_category_id
and pct.product_category_name not in ('GROCERIES', 'CLOTHES')
and s.sale_dt >= trunc(add_months(sysdate, -6), 'mm');

Запрос объединяет информацию о продажах за последние полгода и работает медленно.
На основании данных отчёта sql-мониторинга и информации ниже нужно понять, на каких этапах висит запрос. Какие действия можно предпринять, чтобы его ускорить, не меняя при этом текст запроса?



Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------

1 — SEL$1
5 — SEL$1 / S@SEL$1
6 — SEL$1 / P@SEL$1
7 — SEL$1 / PCT@SEL$1
8 — SEL$1 / PCT@SEL$1

Outline Data
-------------

/*+
BEGIN_OUTLINE_DATA
NLJ_BATCHING(@"SEL$1" "PCT"@"SEL$1")
USE_NL(@"SEL$1" "PCT"@"SEL$1")
USE_NL(@"SEL$1" "P"@"SEL$1")
LEADING(@"SEL$1" "S"@"SEL$1" "P"@"SEL$1" "PCT"@"SEL$1")
INDEX(@"SEL$1" "PCT"@"SEL$1" ("PRODUCT_CATEGORIES"."PRODUCT_CATEGORY_ID"))
FULL(@"SEL$1" "P"@"SEL$1")
FULL(@"SEL$1" "S"@"SEL$1")
OUTLINE_LEAF(@"SEL$1")
ALL_ROWS
DB_VERSION('12.2.0.1')
OPTIMIZER_FEATURES_ENABLE('12.2.0.1')
IGNORE_OPTIM_EMBEDDED_HINTS
END_OUTLINE_DATA
*/

Predicate Information (identified by operation id):
---------------------------------------------------

5 — filter("S"."SALE_DT">=TRUNC(ADD_MONTHS(SYSDATE@!,(-6)),'fmmm'))
6 — filter("P"."PRODUCT_ID"="S"."PRODUCT_ID")
7 — access("PCT"."PRODUCT_CATEGORY_ID"="P"."PRODUCT_CATEGORY_ID")
8 — filter("PCT"."PRODUCT_CATEGORY_NAME"<>'GROCERIES' AND "PCT"."PRODUCT_CATEGORY_NAME"<>'CLOTHES')


Я решил так: Создать индексы по product_category_name и s.sale_dt как trunc(sysdate) и партиционировать таблицу sales по полю sale_dt

Может что то еще можно сделать?