Répondre

3

Vous voulez absolument éviter l'utilisation de tout custom or built-in functions wrapping a column in a filter - elle limite sévèrement ce que l'optimiseur peut faire pour vous en termes d'utilisation et seekability index. Vous devriez prendre l'habitude d'utiliser des opérateurs d'égalité et/ou des approches de/union lorsque cela est possible, comme c'est le cas ici. Seraient préféré bien sur une approche isnull() ou s'unir():

where (
      (t.email is null) 
      or 
      (t.email = '') 
     ) 

ou une approche syndicale tel que décrit ci-dessous qui pourrait mieux fonctionner aussi bien, essayer dans votre environnement pour déterminer quelle est la meilleure option.

Un exemple simple démontrera les différences drastiques que vous pouvez voir dans la performance:

use tempdb; 
go 
if object_id('tempdb..#testTable') > 0 
    drop table #testTable; 
go 
-- Build the dataset 
select top 10000000 
     cast(cast(a.name as varchar(100)) + '@' + cast(row_number() over (order by a.object_id) as varchar(15)) + '.com' as varchar(150)) as email, 
     row_number() over (order by a.object_id) as id 
into #testTable 
from sys.columns a 
cross join sys.columns b 
cross join sys.columns c 
go 
-- Create some nulls 
update #testTable 
set  email = null 
where id % 1000 = 0 
go 
-- Index 
create unique clustered index ixc__dbo_testTable__temp__nc1 on #testTable (email,id) on [default]; 
go 
set statistics io on; 
set statistics time on; 
go 
-- Try with isnull - ~cost of about 44.7 on my machine, ~2900ms to execute, and about 49,200 logical reads 
select * 
from #testTable t 
where isnull(t.email,'') = ''; 
go 
-- Try with 'or' - ~cost of about .049 on my machine, ~643ms to execute, about 31 logical reads 
select * 
from #testTable t 
where (
      (t.email is null) 
      or 
      (t.email = '') 
     ); 
go 
-- Try with union approach - ~cost of about .054 on my machine, ~751ms to execute, ~30 logical reads 
select * 
from #testTable t 
where t.email is null 
union all 
select * 
from #testTable t 
where t.email = ''; 
go 
if object_id('tempdb..#testTable') > 0 
    drop table #testTable; 
go 
+0

C'est génial, je vais essayer - thx. – Ice

0

Si vous allez voir des différences de performance, ils seront minuscules.

je crois que le style préféré est

ISNULL(email, '') = '' 
+0

Les différences de performance peuvent être très dramatiques - l'optimiseur n'est pas très prévisible pour optimiser les filtres entourés de fonctions. Voir un test simple ci-dessous pour vérification. SARGability est un terme parfois utilisé ici, même si ce n'est pas exactement la même chose. – chadhoc