Гость
Map
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Как улучшить детерминированную функцию при парсере строки ? / 3 сообщений из 3, страница 1 из 1
11.11.2021, 19:32
    #40111143
максим_1991
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как улучшить детерминированную функцию при парсере строки ?
В таблице строки:

MK~RU_AR~ZEN_MB~CKONE_CN~ADFORM_CP~3301071970_CI~FY22Q1-RU-CK-CKON-NK-NO_OB~AWA_IT~SOC_OB~AWA_TG~DEMINT_PB~VK_AS~VK_BT~AUCTION_CH~VIDEO_RA~CPM_FM~VID_DT~CROSS_SZ~1X1_TS~ADU_ST~FILGEO_AD~STAND_PK~REA_AV~BEA_PD~PPV-123895_VV~NONE_PI~123895_ID~GLD0009ADF__MB~CKONE_FM~VID_CS~1X1_CV~PPV-123895_FF~CPM__

MK~RU_AR~ZEN_MB~GUCCIFLRA_CN~ADFORM_CP~3301061855_CI~FY22Q1-RU-GU-GUGF-NK-NO_OB~AWA_IT~RON_OB~AWA_TG~DEMINT_PB~MEGOGO_AS~NONE_BT~PROG_CH~VIDEO_RA~CPM_FM~VID_DT~CROSS_SZ~1X1_TS~ADU_ST~FILGEO_AD~ST_PK~REA_AV~BEA_PD~MEGOGO-BRANDING-123118-LE_VV~NONE_PI~123118_ID~GLD00098E1__MB~GUCCIFLRA_FM~VID_CS~1X1_CV~MEGOGO-BRANDING-123118-LE_FF~LETU__

Надо отобрать числа по маске : '(\D|^)(\d{5,6})(\D|$)' записав в строку через разделитель ';' без повторений,

Написал функцию, но она работает медленно на большом колличестве данных.

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
create or replace FUNCTION get_distinct_dbs (
  p_dbs_list    IN  VARCHAR2
) RETURN varchar2 DETERMINISTIC
AS
  p_result      varchar2(32767);
BEGIN
select listagg(dbs_distinct, ';')  Within Group (Order By dbs_distinct) into p_result
from 
(Select distinct regexp_substr(regexp_replace(upper(p_dbs_list), '(CR\d{6})|(\D)', '__'), '(\D|^)(\d{5,6})(\D|$)', 1, LEVEL, 'i', 2) dbs_distinct
                         From dual
                         Where 1 = 1
                         Connect By LEVEL <= regexp_count(upper(p_dbs_list),'(\D|^)(\d{5,6})(\D|$)'))

;
  RETURN p_result;
END;



Как написать быструю детерминированную функцию используя pl sql ?
...
Рейтинг: 0 / 0
11.11.2021, 22:45
    #40111164
Dubanos_II
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как улучшить детерминированную функцию при парсере строки ?
максим_1991,

если вам необходима именно функция заданной сигнатуры, можно попробовать отказаться от регулярок

Например, так (и это всё еще отнюдь не оптимальный код):
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
create or replace function my_dbs(
    p_dbs in varchar2
) return varchar2 deterministic as
    c_minlen        integer := 5;
    c_maxlen        integer := 6;
    
    type values_t is table of varchar2(1 char) index by varchar2(10 char);
    
    t_values                values_t := values_t();

    l_ret                   varchar2(4000 char);
    l_char                  varchar2(1 char);
    l_buffer                varchar2(10 char);
    l_idx                   varchar2(10 char);
    l_is_possible_match     boolean := true;
begin
    for i in 1..length(p_dbs)
    loop
        l_char := substr(p_dbs, i, 1);
        if nvl(length(replace(translate(l_char, '0123456789', rpad(chr(1), 10, chr(1))), chr(1))), 0) = 0
        then -- char is number
            if l_is_possible_match and nvl(length(l_buffer),0) < c_maxlen
            then
                l_buffer := l_buffer || l_char;
            else
                l_buffer := '';
                l_is_possible_match := false;
            end if;
        else --char is not number
            if l_is_possible_match and nvl(length(l_buffer),0) >= c_minlen
            then
                t_values(l_buffer) := 'x';
                l_buffer := '';
            elsif l_is_possible_match and nvl(length(l_buffer),0) < c_minlen
            then
                l_buffer := '';
            else
                l_is_possible_match := true;
            end if;
        end if;
    end loop;
    
    if nvl(length(l_buffer),0) >= c_minlen
    then
        t_values(l_buffer) := 'x';
    end if;
    
    l_idx := t_values.first;
    while (l_idx is not null)
    loop
        l_ret := l_ret || ';' || l_idx;
        l_idx := t_values.next(l_idx);
    end loop;
    
    return ltrim(l_ret, ';');
end;



проверил скриптом
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
declare
    l_start timestamp with local time zone;
    l_ret   varchar2(4000 char);
begin
    l_start := systimestamp;
    
    for i in 1..1000
    loop
        l_ret := my_dbs('MK~RU_AR~ZEN_MB~CKONE_CN~ADFORM_CP~3301071970_CI~FY22Q1-RU-CK-CKON-NK-NO_OB~AWA_IT~SOC_OB~AWA_TG~DEMINT_PB~VK_AS~VK_BT~AUCTION_CH~VIDEO_RA~CPM_FM~VID_DT~CROSS_SZ~1X1_TS~ADU_ST~FILGEO_AD~STAND_PK~REA_AV~BEA_PD~PPV-123895_VV~NONE_PI~123895_ID~GLD0009ADF__MB~CKONE_FM~VID_CS~1X1_CV~PPV-123895_FF~CPM__');
    end loop;
    
    dbms_output.put_line(l_start - systimestamp);
    
    l_start := systimestamp;
    
    for i in 1..1000
    loop
        l_ret := get_distinct_dbs('MK~RU_AR~ZEN_MB~CKONE_CN~ADFORM_CP~3301071970_CI~FY22Q1-RU-CK-CKON-NK-NO_OB~AWA_IT~SOC_OB~AWA_TG~DEMINT_PB~VK_AS~VK_BT~AUCTION_CH~VIDEO_RA~CPM_FM~VID_DT~CROSS_SZ~1X1_TS~ADU_ST~FILGEO_AD~STAND_PK~REA_AV~BEA_PD~PPV-123895_VV~NONE_PI~123895_ID~GLD0009ADF__MB~CKONE_FM~VID_CS~1X1_CV~PPV-123895_FF~CPM__');
    end loop;
    
    dbms_output.put_line(l_start - systimestamp);
end;



получил:
Код: plsql
1.
2.
3.
Statement processed.
-000000000 00:00:00.000996000
-000000000 00:00:00.003733000



альтернативный вариант - реализовать обработку всех имеющихся строк в одном SQL-запросе. Выиграете на переключении контекста и за счет внутренних механизмов оптимизации
...
Рейтинг: 0 / 0
15.11.2021, 11:29
    #40112017
максим_1991
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как улучшить детерминированную функцию при парсере строки ?
Dubanos_II, Благодарю Вас )
...
Рейтинг: 0 / 0
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Как улучшить детерминированную функцию при парсере строки ? / 3 сообщений из 3, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]