CftClub.ru
Клуб специалистов ЦФТ-Банк

Почему нельзя использовать так?

 
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Разработка в PL/PLUS. Оптимизация запросов Oracle
Предыдущая тема :: Следующая тема  
Автор Сообщение
arkazar
Участник со стажем


Вступление в Клуб: 27.09.2010
СообщениеПт Дек 21, 2012 14:39   Почему нельзя использовать так? Ответить с цитатой
Полезность: Нет оценки
Всем, Привет!

Подскажите, почему так работает:

where prop.[GROUP_PROP].[CODE] in ('NRD_CL_2171_CD','NRD_CL_2171_CB','NRD_CL_2171_P','NRD_CL_2171_CS','NRD_CL_2171_CBS','NRD_CL_2171_KF','NRD_CL_2171_VP','NRD_CL_RELATION')

А так нет? :

str_val string;
begin
str_val:=::[FP_TUNE].[LIB].get_str_value('NRD_CL_2171');

debug_pipe('str_val='||str_val,0);

for (select x(x.[GROUP_PROP].[CODE] oper_code) in Prop_arr

where x.[GROUP_PROP].[CODE] in (str_val)
)
loop
vtar
Эксперт


Вступление в Клуб: 20.03.2009
СообщениеПт Дек 21, 2012 14:45    Ответить с цитатой
Полезность: Нет оценки
потому, что синтаксис.

in подразумевает последовательность аргументов.

если нужно пробежаться по сборной строке параметров, нужно что то вроде where instr(str_val,code ) > 0
arkazar
Участник со стажем


Вступление в Клуб: 27.09.2010
СообщениеПт Дек 21, 2012 15:14    Ответить с цитатой
Полезность: Нет оценки
Не совсем понял...

это куда надо? inst же выводит значениие позиции фразы....
Volod
Эксперт


Вступление в Клуб: 19.09.2007
СообщениеПт Дек 21, 2012 15:28    Ответить с цитатой
Полезность: Нет оценки
Используйте regexp_like
vtar
Эксперт


Вступление в Клуб: 20.03.2009
СообщениеПт Дек 21, 2012 15:28    Ответить с цитатой
Полезность: Нет оценки
как то так

for (select x(x.[GROUP_PROP].[CODE] oper_code) in Prop_arr

where substr(str_val,x.[GROUP_PROP].[CODE] ) >0
loop

ну и для полного щастья обвесить trim, upper и nvl Smile
vtar
Эксперт


Вступление в Клуб: 20.03.2009
СообщениеПт Дек 21, 2012 15:31    Ответить с цитатой
Полезность: Нет оценки
Volod пишет:
Используйте regexp_like

Вы ещо аналитические функции Запросчику посоветуйте
8( )
Volod
Эксперт


Вступление в Клуб: 19.09.2007
СообщениеПт Дек 21, 2012 15:45    Ответить с цитатой
Полезность: Нет оценки
Шаблон несложный:

where regexp_like(prop.[GROUP_PROP].[code], '^(NRD_CL_2171_CD|NRD_CL_2171_CB|NRD_CL_2171_P|NRD_CL_2171_CS|NRD_CL_2171_CBS|NRD_CL_2171_KF|NRD_CL_2171_VP|NRD_CL_RELATION)')
Random
Эксперт


Вступление в Клуб: 27.06.2011
СообщениеПн Дек 24, 2012 13:57    Ответить с цитатой
Полезность: Нет оценки
Volod пишет:
Шаблон несложный:

where regexp_like(prop.[GROUP_PROP].[ code ], '^(NRD_CL_2171_CD|NRD_CL_2171_CB|NRD_CL_2171_P|NRD_CL_2171_CS|NRD_CL_2171_CBS|NRD_CL_2171_KF|NRD_CL_2171_VP|NRD_CL_RELATION)')


Если не считать того, что регулярные выражения тут нафик не нужны, а только кушают ресурсы...

Вы же на марсолёте на работу не летаете каждый день?

Код:

declare
str_val varchar2(32767) := 'NRD_CL_2171_CD,NRD_CL_2171_CB,NRD_CL_2171_P,NRD_CL_2171_CS,NRD_CL_2171_CBS,NRD_CL_2171_KF,NRD_CL_2171_VP,NRD_CL_RELATION';
begin
for (select x(x.[GROUP_PROP].[ CODE ] oper_code) in Prop_arr

where instr( ',' || str_val || ','
                 ,',' || x.[GROUP_PROP].[ code ] || ',' ) >0
loop
...


1. instr с null возвращает null. Если строка никогда не будет пустой, эту ветку можно не обрабатывать.
2. данный instr обрабатывает обе ситуации, когда строка приходит с начинающей запятой и завершающей запятой, или без них.
3. Разделитель, естественно, любой, в ЦФТ часто используют #
4. запрос с in использует индекс, запрос с instr может использовать индекс (но уже не в этом условии) - /дальше много буков об оптимизации/ это вопрос к оптимальности. Если результат запроса с in даёт < 5% таблицы, лучше in, если больше - instr, опять же instr даёт возможность использовать другие индексы, типа с collection_id, точнее не искушает оптимизатор Oracle сойти с нужного индекса.
Reddom
Участник со стажем


Вступление в Клуб: 25.01.2013
СообщениеПт Янв 25, 2013 09:36    Ответить с цитатой
Полезность: Нет оценки
Так мне кажется будет быстрее (В pl+ переделывается в минуты, суть разбить строку на части и превратить в табличку, из которой работает выборка по IN):

Код:
select * from Z#MAIN_DOCUM where id in (
select
      regexp_substr(str, '[^,]+', 1, level) as codes
from
     (select '13209770,13209786,13209802,13207482' as "STR" from dual)
connect by level <= regexp_count(str, '[^,]+'));


План выполнения:

Код:
SELECT STATEMENT, GOAL = ALL_ROWS         Cost=4   Cardinality=1   Bytes=543
 NESTED LOOPS               
  NESTED LOOPS         Cost=4   Cardinality=1   Bytes=543
   VIEW   Object owner=SYS   Object name=VW_NSO_1   Cost=3   Cardinality=1   Bytes=19
    HASH UNIQUE         Cost=3   Cardinality=1   
     CONNECT BY WITHOUT FILTERING (UNIQUE)               
      FAST DUAL         Cost=2   Cardinality=1   
   INDEX UNIQUE SCAN   Object owner=IBS   Object name=PK_Z#MAIN_DOCUM_ID   Cost=1   Cardinality=1   
  TABLE ACCESS BY INDEX ROWID   Object owner=IBS   Object name=Z#MAIN_DOCUM   Cost=1   Cardinality=1   Bytes=524
Random
Эксперт


Вступление в Клуб: 27.06.2011
СообщениеПн Янв 28, 2013 16:22    Ответить с цитатой
Полезность: Нет оценки
Reddom пишет:
Так мне кажется будет быстрее (В pl+ переделывается в минуты, суть разбить строку на части и превратить в табличку, из которой работает выборка по IN):

Код:
select * from Z#MAIN_DOCUM where id in (
select
      regexp_substr(str, '[^,]+', 1, level) as codes
from
     (select '13209770,13209786,13209802,13207482' as "STR" from dual)
connect by level <= regexp_count(str, '[^,]+'));


План выполнения:

Код:
SELECT STATEMENT, GOAL = ALL_ROWS         Cost=4   Cardinality=1   Bytes=543
 NESTED LOOPS               
  NESTED LOOPS         Cost=4   Cardinality=1   Bytes=543
   VIEW   Object owner=SYS   Object name=VW_NSO_1   Cost=3   Cardinality=1   Bytes=19
    HASH UNIQUE         Cost=3   Cardinality=1   
     CONNECT BY WITHOUT FILTERING (UNIQUE)               
      FAST DUAL         Cost=2   Cardinality=1   
   INDEX UNIQUE SCAN   Object owner=IBS   Object name=PK_Z#MAIN_DOCUM_ID   Cost=1   Cardinality=1   
  TABLE ACCESS BY INDEX ROWID   Object owner=IBS   Object name=Z#MAIN_DOCUM   Cost=1   Cardinality=1   Bytes=524


Интересное решение. А не пробовали nested_varray применить?
devor
Профи


Вступление в Клуб: 13.02.2012
СообщениеВт Янв 29, 2013 07:35    Ответить с цитатой
Полезность: 1
Применение сложных решений для простых задач сильно портит карму.
Сопровождающие такой код будут потом долго вспоминать разработчика ласковыми выражениями.
Reddom
Участник со стажем


Вступление в Клуб: 25.01.2013
СообщениеЧт Янв 31, 2013 14:25    Ответить с цитатой
Полезность: Нет оценки
Random пишет:
Интересное решение. А не пробовали nested_varray применить?

К данному случаю, я считаю, что не имеет особого смысла:
Код:
VIEW   Object owner=SYS   Object name=VW_NSO_1   Cost=3   Cardinality=1   Bytes=19
    HASH UNIQUE         Cost=3   Cardinality=1   
     CONNECT BY WITHOUT FILTERING (UNIQUE)               
      FAST DUAL         Cost=2   Cardinality=1

Видно, что создается псевдовьюха с кодами и стоимость её 3, чтения с диска нет и т.п.. Так что по стоимости в производительности выигрыша максимум cost = 1. Ну и как плюс приведенное решение можно использовать в чистом sql, например представлениях.

devor пишет:
Применение сложных решений для простых задач сильно портит карму.
Сопровождающие такой код будут потом долго вспоминать разработчика ласковыми выражениями.


Качественно хороший и правильно оформленный с комментариями даже очень сложный код читается не хуже "китайского кода", где вместо sql предпочитают пользоваться многоразовым вызовом интерфейса, который, если прочитать код, все равно каждый раз производит чтение с таблицы sql запросом. И тут уже вопрос в производительности. Connect by level вполне освояем прочтением документации Oracle в течении 10-20 минут. Регулярные выражения чуть дольше, но выигрыш в производительности окупает в десятки раз потерянное время "сопровождающих" код. К приведенному мной примеру можно комментарием вставить:
Код:
/*разбиваем строку на id по запятым*/
devor
Профи


Вступление в Клуб: 13.02.2012
СообщениеЧт Янв 31, 2013 15:44    Ответить с цитатой
Полезность: Нет оценки
Reddom пишет:

devor пишет:
Применение сложных решений для простых задач сильно портит карму.
Сопровождающие такой код будут потом долго вспоминать разработчика ласковыми выражениями.


Качественно хороший и правильно оформленный с комментариями даже очень сложный код читается не хуже "китайского кода", где вместо sql предпочитают пользоваться многоразовым вызовом интерфейса, который, если прочитать код, все равно каждый раз производит чтение с таблицы sql запросом. И тут уже вопрос в производительности. Connect by level вполне освояем прочтением документации Oracle в течении 10-20 минут. Регулярные выражения чуть дольше, но выигрыш в производительности окупает в десятки раз потерянное время "сопровождающих" код. К приведенному мной примеру можно комментарием вставить:
Код:
/*разбиваем строку на id по запятым*/

Зачем тут иерархические запросы и регулярные выражения, когда достаточно простого instr, что и было сразу предложено изначально?
Инструменты надо подбирать исходя из поставленной задачи - гвоздь можно забить шуруповертом, но неудобно.

А реплика про "Китайский код" с интерфейсами и вовсе непонятно в какую кассу.
devor
Профи


Вступление в Клуб: 13.02.2012
СообщениеЧт Янв 31, 2013 16:20    Ответить с цитатой
Полезность: Нет оценки
Надеюсь, понятно, что id имеет индекс, поэтому такой красивый план?
Он(план) будет совсем другим для поля без индекса, например, c_num_check
Reddom
Участник со стажем


Вступление в Клуб: 25.01.2013
СообщениеПт Фев 01, 2013 08:18    Ответить с цитатой
Полезность: Нет оценки
devor пишет:
Надеюсь, понятно, что id имеет индекс, поэтому такой красивый план?
Он(план) будет совсем другим для поля без индекса, например, c_num_check

Идея моего запроса и была в том, чтобы запрос встал на индекс. Если поле без индекса, то в полне подойдет вариант предложенный Volod, который по мне так более читабельный, чем с instr:
Volod пишет:
Шаблон несложный:

where regexp_like(prop.[GROUP_PROP].[code], '^(NRD_CL_2171_CD|NRD_CL_2171_CB|NRD_CL_2171_P|NRD_CL_2171_CS|NRD_CL_2171_CBS|NRD_CL_2171_KF|NRD_CL_2171_VP|NRD_CL_RELATION)$')


По себе, так я не вижу разницы в выборе инструментов, главное чтобы работало быстро и качественно. А про "китайский код", я имел ввиду, что читаемость кода достигается граммотными комментариями в сложных местах, а не выбором/копированием набитых шаблонов, которые увеличивают время обработки за счет "универсальности" и, возможно, стабильности, зато легко исправляемы какими-либо параметрами. Но каждый выбирает свой путь - я лишь предложил решение и высказал мнение Very Happy
Показать сообщения:   
Ответить на тему    Клуб специалистов ЦФТ-Банк (IBSO) -> Разработка в PL/PLUS. Оптимизация запросов Oracle Часовой пояс: GMT + 3
Страница 1 из 1

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Рейтинг@Mail.ru