WHERE yan tümcesindeki bir değişkeni null olarak denetlemenin bir yolu var mı?


12

Ben böyle görünüyor büyük bir tabloda bir sorgu var:

declare @myIdParam int = 1

select * 
from myTable
where (@myIdParam is null or myTable.Id = @myIdParam)

Burada bulunan maddede bunun gibi birkaç benzer koşul vardır ve çok sayıda birleşim de vardır, ancak bu bir özettir.

Etkili bir şekilde @ myIdParam null olursa, bu parametreyi kullanarak sonuçları kısıtlamak istemiyoruz.

Ben bir DB pro değilim, ama benim testleri bu NULL kontrol her kayıt için yapılır ve herhangi bir şekilde optimize değil gibi görünüyor.

Boş denetimi kaldırır ve parametrenin boş olmadığını varsayarsam, sorgu anında geri döner. Aksi takdirde, on saniye sürer.

Kontrolün çalışma zamanında yalnızca bir kez yapılması için bunu optimize etmenin bir yolu var mı?


1
Şu cevaba bakın: stackoverflow.com/questions/3415582/… tl; dr useOPTION(RECOMPILE)
vercelli

@vercelli bu hile yapar. Bu sorunun gerçekten isteğe bağlı parametrelerle ilgili olduğunu düşünürsek, bunun bağlandığınızın bir kopyası olduğunu söyleyebilirim.
Mystagogue

Muhtemelen, ama 6 yıl önce bir yazı. Belki SqlServer 2014 veya 2016 ile yeni bir yaklaşım var. (2014'te yeniden
derlemeden

Gerçek sorgunuzda isteğe bağlı birçok parametre bulunduğundan, dinamik SQL en iyi performansı sağlayacaktır. Konuyla ilgili ayrıntılı bir makale için sommarskog.se/dyn-search.html adresine bakın .
Dan Guzman

@DanGuzman bağlı vercelli bağlantılı soru ile WITH RECOMPILE kullanarak sorgu süresi hemen bir dakikadan son derece seçici kriterler ile pratik anında kesilir. Bunu performans ve okunabilirliği dengelemek için en iyi seçenek olarak görüyorum.
Mystagogue

Yanıtlar:


8

Bunun bir yolu, isteğe bağlı olarak where yan tümcesinin bir kısmını eklemek için boş bir denetim kullanarak dinamik SQL kullanmaktır.

declare @myIdParam int = 1
declare @vc_dynamicsql varchar(max)

set @vc_dynamicsql = 'select * from myTable where 1=1'

if @myIdParam is not null
    set @vc_dynamicsql = @vc_dynamicsql + ' and  myTable.Id = @myIdParam'

EXECUTE sp_executesql @vc_dynamicsql

2
Bunu yapmamayı gerçekten tercih ederim, ama bu bir çözüm. Umudum, birinin çok daha iyi biriyle gelmesidir.
Mystagogue

1
Bu arama sorgusu sınıfını işlemenin en iyi yoludur. @Vercelli tarafından değinilen stackoverflow cevabı bunun nasıl büyük referanslar içerir.
Max Vernon

Bu en iyi yöntem ama @params parametresi için sp_ExecuteSQLeksik olduğunu ve @vc_dynamicsqlparametre bir olması gerektiğini fark ettim NVARCHAR.
James Anderson

4

Bir işlevi `` ISNULL (@var, table.col) '' sütununa her yerleştirdiğinizde, örneğin SQL'in bir dizin kullanma yeteneğini kaldırırsınız. Tek bir sorguda tutmak istiyorsanız, bu gerçekten en iyi performans gösteren seçenektir.

@var IS NULL or @var = table.col

Aksi takdirde iki seçeneğiniz vardır. Birincisi dinamik SQL ve @ Mystagogue'un cevabı bunun için yeterli, aksi takdirde böyle iki sorgu koyabilirsiniz:

IF @var is NULL
     SELECT * FROM table
ELSE
     SELECT * FROM table WHERE @var = col

Hem bu formatta hem de dinamik SQL'de her bir sorgu için farklı bir sorgu planı elde edersiniz (bu da potansiyel olarak daha iyi performans sağlayacaktır).


Sorudaki Sql ISNULL veya başka bir işlev kullanmıyor.
Mystagogue

Şimdi silinmiş bir cevaba atıfta bulunuyordum.
Kenneth Fisher

0

Peki, şunları yapabilirsiniz:

declare @myIdParam int = 1;

select *
from myTable
where nullif(@myIdParam, myTable.Id) is null;

Bununla birlikte, nullif()işlevin aslında bir sarıcı olduğunu unutmayın case. ORSorguyu sihirli bir şekilde ortadan kaldıran ve hızlandıran gümüş bir kurşun değildir .


bir yan tümcesinde işlevleri kullanmak performans üzerinde olumsuz bir etkiye sahiptir, çünkü dizinlerin kullanımını engeller (ya da duydum)
Mystagogue

@Mystagogue, evet - arama koşullarını genellikle SARGable yapmaz hale getirir. Ne yazık ki, dinamik SQL veya çoklu UNIONs'ye başvurmadan sorunuzu nasıl cevaplayacağımı bilmemin tek yolu bu . Bu tam görevim olduğunda dinamik SQL seçtim.
Roger Wolf
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.