İlk önce SQL'de yürütülen işlevlere güvenebilir miyim


9

Lütfen aşağıdaki komut dosyasını göz önünde bulundurun:

create or replace function f(p_limit in integer) return integer as
begin
  set_global_context ('limit', p_limit);
  return p_limit;
end;
/

create view v as 
select level as val from dual connect by level<=sys_context('global_context','limit');

select f(2), v.* from v;

/*
F(2)                   VAL                    
---------------------- ---------------------- 
2                      1                      
2                      2                      
*/

select f(4), v.* from v;

/*
F(4)                   VAL                    
---------------------- ---------------------- 
4                      1                      
4                      2                      
4                      3                      
4                      4                      
*/

f(x)10.2'de çalıştırılan bu test senaryosunda olduğu gibi, içerik görünüm içinde okunmadan önce yürütülmeye güvenebilir miyim ?


Yardım edemem ama bir giriş tetikleyicisinin daha uygun olabileceğini düşünün (seviye her zaman aynı olacaksa, yani)
Philᵀᴹ

@Phil bu sadece bir örnektir - Bir görünümü parametreleştirmek için sys_context kullanıyorum ve parametre her seferinde farklı olacak. Eğer böyle bir karışıklık olmadan SQL küresel bir bağlam ayarlamak için bir yol biliyorsanız, ben de duymak isterim!
Jack diyor ki topanswers.xyz

1
@JackDouglas: bir görüşü parametreleştirmek bana doğru hissetmeyen bir fikir. MSSQL altında yapmaya çalıştığınız şey, bir sonuç kümesi (değer yerine) döndüren kullanıcı tanımlı bir işlev kullanılarak yapılabilir - o zaman SELECT stuff FROM dbo.FuncReturningTable(param)veya benzeri. Oracle muhtemelen aynı işlevselliğe sahiptir. Büyük veri kümeleri üzerinde bu kullanarak performans izlemek için dikkatli olsanız da: Sorgu planlayıcısı böyle bir sözdiziminden verimli bir plan yapmak için ne kadar parlak olması gerekir emin değilim.
David Spillett

@David parametreleme bir görünüm genellikle sys_context ile yapılır - sadece normalde sorguyu çalıştırmadan önce içeriği ayarlarsınız (örn. Biraz PL / SQL ile). Oracle'ın geri dönen ve / veya ardışık düzen işlevleri vardır, ancak bunu başarmanın 'normal' yolu değildir. Açık olmak gerekirse, başlıktaki sorunun cevabının "hayır" olduğunu düşünüyorum - Birisinin daha iyi bilip bilmediğini merak ettim.
Jack diyor ki topanswers.xyz

Yanıtlar:


8

Hayır.

Görünümünüzü, nereye göre bağlama yerine (yerine bağlanmak yerine) bağlam filtrelemesiyle yeniden yazarsanız, bağlam için önceden ayarlanmış değeri alırsınız:

create table t as 
 select rownum r from dual connect by level <= 10;

create or replace view v as 
  select r val from t where r <=sys_context('global_context','limit');

select f(2), v.* from v;

F(2) VAL
---- ---
   2   1 
   2   2 

select f(4), v.* from v;

F(4) VAL
---- ---
   4   1 
   4   2 

select f(4), v.* from v;

F(4) VAL
---- ---
   4   1 
   4   2 
   4   3 
   4   4 

Where cümlesi, sütunlar seçilmeden önce değerlendirildiğinden, işleve iletilen değer bağlam okunana kadar ayarlanmaz. Sorgunuzdaki sys_context çağrısının konumu (select, where, group by, vb.) Bu değer ayarlandığında tam olarak etkilenir.


+1, kitabımda hemen hemen "dava kapandı", teşekkürler.
Jack diyor ki topanswers.xyz

2

Genel olarak konuşursak, tek bir SQL ifadesini değerlendirirken DBMS'nizin bir şeyler yapacağı sıra hakkında güvenli bir şekilde hiçbir şey üstlenemezsiniz. Bu nedenle birçok DBMS, bu şekilde kullanılan işlevlerin yan etkilere sahip olmasına izin vermez (örn. MSSQL, işlevlerin orada yaptığınız genel / bağlantı durumunu ayarlamasına veya tablo içeriğini değiştirmesine izin vermez). Bir dizi ifade, bir adımdan diğerine mantıklı bir şekilde yürütülmelidir (yani, seri olarak çalıştırılırlar veya olmadıklarını söyleyemeyeceğiniz bir şekilde), ancak tek bir ifade içinde sorgu planlayıcısı zaten bulunmadığı yerlerde belirsizlik getirmediği sürece serbest saltanatı vardır (örneğin, işlevde bir yan etkisi olduğu için belirsizlik zaten vardır).

Sorgu planlayıcısı, görünümün işlevin yan etkilerinden etkilendiğini algılayacak kadar parlak olsaydı, bu işlevi potansiyel olarak farklı giriş değerleriyle çağıran başka bir görünüme katılırsanız ne yapardı? Oldukça hızlı bir şekilde çok kıllı olabilir - bu tür bir şey genellikle, herhangi bir programlama bağlamında, işlevlerin kendi çıktılarının ötesinde etkileri olmamalıdır.

Bu özel örnekte, f (x) ifadesinin ilk olarak çağrılmasının pek mümkün olmadığını söyleyebilirim, çünkü ifadenin bir kısmını "görüntüleyebilir": görünümdeki sonuç kümesi, herhangi bir işlevden önce alınacaktır. döndürülecek sütunların listesi değerlendirilir. Tabii ki bu kullanılan DBMS bağlı olarak değişecektir: Ben Oracle uzmanı değilim ve test sonuçlarınız bu durumlarda ilk olarak çağrılıyor gibi görünüyor. Ancak, herhangi bir SQL ifadesi içinde yürütme sırasına tamamen güveniyorum - her zaman beklediğiniz şekilde çalışsa bile, gelecekteki revizyonlarda bunu yapmayabilir (resmi olarak yürütmenin her zaman gideceği bir yerde belgelenmedikçe) bu şekilde).


2
Güzel cevap, ama Jack'in kesin bir teknik Oracle cevabı aradığını hissediyorum.
Philᵀᴹ

1

Belgeler yalnızca "Optimize Edici önce sabitleri içeren ifadeleri ve koşulları olabildiğince tam olarak değerlendirir." ( 10.2 , 11.2 ). Öncelikle belirli bir ifadeyi değerlendireceği veya bu sırayı zaman zaman değiştirmeyeceği (aynı sürümdeki yeni bir yama düzeyi?) Garanti edilmez.


+1 mükemmel, teşekkürler (okumaya rağmen bu dokümanlar Chris'in cevabı ile pek kare değil )
Jack diyor ki topanswers.xyz

1
Fark, işlevin where, select veya başka bir yan tümcede çağrılmasıdır. Seçim bölümündeki işlevler optimize edici kararlarını etkilemez (alt sorgu olmadığı sürece), sonuç alınana kadar bunların değerlendirilmesi gerekmez. Where yan tümcesindeki işlevler yine de kullanılan birleştirme yöntemini etkileyecektir, bu nedenle mümkün olan en kısa sürede değerlendirilmesi gerekir.
Chris Saxon

@Chris konuşma deneyimi mi yoksa bunu dokümanlardan bir yerlerde mi aldınız?
Jack diyor ki topanswers.xyz

Doküman referansı bulamıyorum. Deneyimlerime dayanarak, tek bir tabloya filtre uygulamak için where yan tümcesinde çağrılırsa, her satır için (bir FTS varsayarak) erişilir, ancak yalnızca seçim listesindeyse döndürülen satırlar için erişilebilir. Yürütme planı ayrıştırma sırasında ayarlandığından, seçimdeki işlevlerin planı etkileyemeyeceği anlamına gelir. Bunu kontrol etmek için bir test durumu, bir sayaç (pakette veya tabloda) ayarlayan bir işlev oluşturup çıktıyı sorgunun nereye yerleştirildiğine göre karşılaştırarak yapılabilir.
Chris Saxon
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.