Ответ на "Закостенелость мышления"


Прочитал я пост "Закостенелость мышления" и вспомнил как я сам часто испытывал внутреннюю борьбу, когда выбирал между скоростью и краткостью при решениях всяких "олимпиадных" задачек. С одной стороны - любовь к perl-гольфу, с другой - любовь к оптимальным быстрым решениям. Как правило, в итоге делал несколько решений.

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

Вот для простого примерчика на табличке с 100тыс. записей и индексом по полю:

ElapsedConsistent gets
С разбиением значений00:00:00.01 7
С обратным like00:00:00.10227
Текст тесткейса:
drop table t purge;

create table t(str primary key) as 
select dbms_random.string('U',10) 
from dual 
connect by level<=1e5;

exec dbms_stats.gather_table_stats(user,'t',cascade => true);

column vals new_value find_us noprint;

select listagg(str,',') within group(order by 1) vals
from t sample(10) 
where rownum<=5;

set serveroutput on autot on

select * 
from t
where 
  t.str in ( select
               regexp_substr('&find_us','[^,]+',1,level) 
             from dual
             connect by level<=regexp_count('&find_us','[^,]+')
           );
           
select *
from t 
where '&find_us' like '%'||t.str||'%';

Comments

Unknown комментирует...

regexp_count в 10g нет.
Как под Oracle 10g переписать запрос?

И select listagg(str,',') within group(order by 1) vals, тоже в 10g не работает.

Sayan Malakshinov комментирует...

Достаточно просто:
select
regexp_substr(:s,'[^,]+',1,level)
from dual
connect by level<=length(:s)-length(translate(:s,'.,','.'))+1

Sayan Malakshinov комментирует...

А вместо listagg можно использовать, например, xmlagg, недокументированный wm_concat или собственные функции как кайтовский stragg.

Отправить комментарий