代码之家  ›  专栏  ›  技术社区  ›  Ice

isNull(email,“)=”不是由它自己解释为(email为空或email='')?

  •  0
  • Ice  · 技术社区  · 15 年前

    作为表演的一个事实,哪一个更好?实际的3个SQL Server版本(2000/2005/2008)之间是否存在差异?

    2 回复  |  直到 15 年前
        1
  •  3
  •   boydc7    15 年前

    你肯定想避免使用任何 custom or built-in functions wrapping a column in a filter -它严重限制了优化器在索引使用和可查看性方面可以为您做什么。您应该养成尽可能使用相等运算符和/或联合方法的习惯,这里就是这样。与isNull()或coalesce()方法相比,以下方法更为可取:

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

    或者下面概述的联合方法也可以更好地工作,在您的环境中进行尝试,以确定哪个选项是最好的。

    一个简单的例子将展示您在性能上看到的巨大差异:

    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
    
        2
  •  0
  •   Justin Niessner    15 年前

    如果你想看到性能的差异,它们会很快出现。

    我认为首选的款式是

    ISNULL(email, '') = ''
    
    推荐文章