2013-06-18 3 views
0

Я действительно новичок в Oracle PL/SQL, но опытный в Sql Server, и я пытаюсь изучить все это. Для вводного я решил оптимизировать запрос, который генерируется как строка C#, а затем выполняется как текст SqlCommand. Поэтому я пытаюсь создать сохраненный процесс, но для включения всех вариантов того, как может быть создано предложение where, оно запустило его на 40 секунд, а сгенерированная строка C# - через 3 секунды. Вот пример того, что я имею в виду вариаций где п ...PL SQL - динамический SQL в предложении where оператора select

declare 
searchType nvarchar2(3); -- options are 'x', 'y', 'z' 
searchDesc nvarchar2(4); -- options are '1', '2', '3' 
searchValue nvarchar2(5); 

begin 

select count(*) 
from tbl_A a 
where ((searchType = 'x' 
    and ((a.desc_X = searchDesc and a.value_1 = searchValue) 
     or (a.desc_X = searchDesc and a.value_2 = searchValue) 
     or (a.desc_X = searchDesc and a.value_3 = searchValue) 
    ) 
) 
    or (searchType = 'y' 
    and ((a.desc_Y = searchDesc and a.value_1 = searchValue) 
     or (a.desc_Y = searchDesc and a.value_2 = searchValue) 
     or (a.desc_Y = searchDesc and a.value_3 = searchValue) 
    ) 
) 
    or (searchType = 'z' 
    and ((a.desc_Z = searchDesc and a.value_1 = searchValue) 
     or (a.desc_Z = searchDesc and a.value_2 = searchValue) 
     or (a.desc_Z = searchDesc and a.value_3 = searchValue) 
    ) 
) 
) 

end; 

Так что мне интересно, можно ли иметь оператор выбора, который может выполнить динамический SQL в ИНЕКЕ. Или весь оператор должен быть динамическим sql. Ниже приведен пример того, что я под сомнение ...

declare 
whereClause varchar2(500); 
searchType nvarchar2(3); -- options are 'x', 'y', 'z' 
searchDesc nvarchar2(4); -- options are '1', '2', '3' 
searchValue nvarchar2(5); 

begin 

select case 
    when searchType = 'x' then 'a.desc_X = :desc and a.value_1 = :val' 
    when searchType = 'y' then 'a.desc_Y = :desc and a.value_2 = :val' 
    when searchType = 'z' then 'a.desc_Z = :desc and a.value_3 = :val' 
    end 
into whereClause 
from dual; 

select count(*) 
from tbl_A a 
where (
    execute immediately whereClause using searchDesc, searchValue 
) 

end; 

Когда я попытался запустить его, как и все динамического SQL, все еще потребовалось ~ 15 секунд, чтобы выполнить. Поэтому, если у кого-то есть лучший способ справиться со многими вариантами предложения, я открыт для предложений.

+0

Что касается вашего вопроса «все ли заявление должно быть динамическим sql», то да. Основываясь на первом примере процедуры и разнице во времени между C# -генерированной версией и proc, я предполагаю, что предложение WHERE в версии proc убивает любые шансы на оптимизацию - возможно, версия C# имеет гораздо более целенаправленную ' WHERE'. Вы можете попробовать дублировать логику C# в процедуре и выполнить «EXECUTE IMMEDIATE» в результирующей строке, но я сомневаюсь, что это даст вам большой импульс. Это может быть случай, когда вам нужно искать оптимизацию в другом месте. –

ответ

2

Слишком много использованных ORs, как правило, придают производительности сосать. Если вы всегда будете иметь фиксированный набор параметров, которые вы можете сделать что-то вроде этого:

declare 

    stmt varchar2(1500); 
    searchType nvarchar2(3); -- options are 'x', 'y', 'z' 
    searchDesc nvarchar2(4); -- options are '1', '2', '3' 
    searchValue nvarchar2(5); 

    n pls_integer; 

begin 

    stmt := 'select count(*) from tbl_A a where ('; 

    case 
     when searchType = 'x' then stmt := stmt || 'a.desc_X = :desc and a.value_1 = :val'; 
     when searchType = 'y' then stmt := stmt || 'a.desc_Y = :desc and a.value_2 = :val'; 
     when searchType = 'z' then stmt := stmt || 'a.desc_Z = :desc and a.value_3 = :val'; 
    end case; 

    stmt := stmt ||')'; 


    execute immediately stmt using searchDesc, searchValue 
    into n; 

end; 

Обратите внимание, что - в отличие от T-SQL - в PL/SQL, мы должны выбрать наш набор результатов в переменную. Я предложил целое число, потому что ваш пример кода - это просто SELECT COUNT (*). Для вашего реального запроса потребуется переменная, соответствующая прогнозу запроса, возможно, типу записи или коллекции.

+0

Да, я думал, что это, вероятно, будет так, как вам придется это делать. Я пытался уйти от необходимости конкатенировать все части запроса в одну строку, так как код C# в настоящее время делает это, и это будет просто перемещать сложность из одной среды в другую. Благодарю за помощь. Я дам этому вопросу немного больше времени, чтобы приготовить, прежде чем я задал это как ответ, чтобы узнать, что еще придумает. – jhorton

Смежные вопросы