Выполнение запроса занимает очень много времени
У меня есть запрос, который занимает часы, а иногда он даже не выполняется. Запрос выглядит следующим образом:
SELECT id, trim(regexp_substr(str, '[^,]+', 1, LEVEL)) str
FROM (SELECT id , MULTILIST01 as str from PAGE_TWO where MULTILIST01 is not null )
WHERE trim(regexp_substr(str, '[^,]+', 1, LEVEL)) is not null
CONNECT BY instr(str, ',', 1, LEVEL -1) > 0;
Результирующий набор запроса
SELECT id , MULTILIST01 as str from PAGE_TWO where MULTILIST01 is not null
это как следует:
ID MULTILIST01
295285 ,3434925,3434442,3436781,
212117 ,3434925,3434442,3436781,
212120 ,3434925,3434442,3436781,
6031650 ,3436781,
.
.
.
Во внешнем запросе я пытаюсь сделать каждое значение через запятую уникальным. Когда я выполняю внешний запрос, это занимает несколько часов. Я пытался оптимизировать его, но это было бесполезно.
Любая идея, как я могу оптимизировать это.
Информация о версии Oracle
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
PL/SQL Release 12.1.0.2.0 - Production
CORE 12.1.0.2.0 Production
TNS for 64-bit Windows: Version 12.1.0.2.0 - Production
NLSRTL Version 12.1.0.2.0 - Production
Объяснить информацию таблицы
Plan hash value: 4097679000
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1429 | 11432 | 840 (2)| 00:00:01 |
|* 1 | FILTER | | | | | |
|* 2 | CONNECT BY WITHOUT FILTERING| | | | | |
|* 3 | TABLE ACCESS FULL | PAGE_TWO | 1429 | 11432 | 840 (2)| 00:00:01 |
------------------------------------------------------------------------------------------
Query Block Name / Object Alias (identified by operation id):
-------------------------------------------------------------
1 - SEL$F5BB74E1
3 - SEL$F5BB74E1 / PAGE_TWO@SEL$2
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(TRIM( REGEXP_SUBSTR ("MULTILIST01",'[^,]+',1,LEVEL)) IS NOT NULL)
2 - filter(INSTR("MULTILIST01",',',1,LEVEL-1)>0)
3 - filter("MULTILIST01" IS NOT NULL)
Column Projection Information (identified by operation id):
-----------------------------------------------------------
1 - "ID"[NUMBER,22], "MULTILIST01"[VARCHAR2,1020], LEVEL[4]
2 - "ID"[NUMBER,22], "MULTILIST01"[VARCHAR2,1020], LEVEL[4]
3 - "ID"[NUMBER,22], "MULTILIST01"[VARCHAR2,1020]
Таблица содержит 225 столбцов, где индекс только по столбцам первичного ключа (ID, CLASS).
Этот стол из Agile PLM.
1 ответ
Ваш подход работает только для таблицы с одной строкой.
SELECT id, trim(regexp_substr(str, '[^,]+', 1, LEVEL)) str
FROM (SELECT id , MULTILIST01 as str from PAGE_TWO where MULTILIST01 is not null and rownum <= 1 )
WHERE trim(regexp_substr(str, '[^,]+', 1, LEVEL)) is not null
CONNECT BY instr(str, ',', 1, LEVEL -1) > 0
order by 1,2;
ID STR
---------- -------------------------
295285 3434442
295285 3434925
295285 3436781
Начиная с таблицы из двух строк, вы получите (вероятно) гораздо больше ожидаемых результатов:
SELECT id, trim(regexp_substr(str, '[^,]+', 1, LEVEL)) str
FROM (SELECT id , MULTILIST01 as str from PAGE_TWO where MULTILIST01 is not null and rownum <= 2 )
WHERE trim(regexp_substr(str, '[^,]+', 1, LEVEL)) is not null
CONNECT BY instr(str, ',', 1, LEVEL -1) > 0
order by 1,2;
ID STR
---------- -------------------------
212117 3434442
212117 3434442
212117 3434925
212117 3436781
212117 3436781
212117 3436781
212117 3436781
295285 3434442
295285 3434442
295285 3434925
295285 3436781
295285 3436781
295285 3436781
295285 3436781
;
Эта переформулировка запроса даст вам (очевидно), что вы хотите. Используйте подзапрос, который доставляет индекс подстроки (1 ..N). Вы должны определить максимальное количество подстрок, которые будут разбиты. Соедините эту таблицу со своей таблицей, чтобы эффективно умножить число строк на N.
with substr_idx as (
select rownum colnum from dual connect by level <= 3 /* max number of substrings */)
SELECT id, trim(regexp_substr(str, '[^,]+', 1, colnum)) str
FROM (SELECT id , MULTILIST01 as str from PAGE_TWO where MULTILIST01 is not null), substr_idx
WHERE trim(regexp_substr(str, '[^,]+', 1, colnum)) is not null
order by 1,2;
ID STR
---------- -------------------------
212117 3434442
212117 3434925
212117 3436781
212120 3434442
212120 3434925
212120 3436781
295285 3434442
295285 3434925
295285 3436781
6031650 3436781
Дальнейшее (незначительное) улучшение производительности ожидается, если вы замените регулярное выражение извлечением substr / instr. Смотрите, например, здесь
Мораль этой истории: если вы не получаете результатов с большими данными, попробуйте с небольшими данными (проверьте rownum <= 2
ограничение выше) и посмотреть, если результаты соответствуют ожидаемым.