【问题标题】:Performance tuning of query查询的性能调优
【发布时间】:2018-04-11 05:56:37
【问题描述】:

我有一个查询需要很长时间才能运行。可能是因为我在连接条件中使用了太多的isnulls。如何通过删除 isnull 来优化它?

有没有不更新表格的替代方法?查询如下:

 select pos.C_id
    ,pos.s_id
    ,pos.A_id
    ,pos.Ad_id
    ,pos.Pr_id
    ,pos.prog_id
    ,pos.port_id
    ,pos.o_type
    ,pos.o_id
    ,pos.s_id
    ,pos.c_id
    ,pos.s_type_id
    ,pos.s_type
    ,pos.e_date
    ,pos.mv
    ,0 is_pub
    , 1 is_adj           
    ,pos.is_unsup
    ,getdate() date
    ,getdate() timestamp
    from #temp pos
    left join acc c with(nolock) ON pos._id = c.c_id
    AND pos.account_id = c.account_id
    AND isnull(pos.Pr_id,0) = isnull(c.pr_id,0)
    AND isnull(pos.prog_id,0) = isnull(c.prog_id,0)
    AND isnull(pos.port_id,0) = isnull(c.port_id,0)
    and isnull(pos.style_type_id,0)=isnull(c.s_type_id,0)
    AND pos.s_id = c._id
    AND pos.c_id = c.c_id
    AND pos.s_type = c.s_type
    AND pos.is_unsup = c.is_uns
    AND pos.is_pub = 1
    where c.a_id is null

【问题讨论】:

  • 检查您的执行计划及其建议。可能正在创建一个覆盖索引可能会对您的情况有所帮助

标签: sql sql-server query-performance


【解决方案1】:

下面的查询呢

 select pos.C_id
    ,pos.s_id
    ,pos.A_id
    ,pos.Ad_id
    ,pos.Pr_id
    ,pos.prog_id
    ,pos.port_id
    ,pos.o_type
    ,pos.o_id
    ,pos.s_id
    ,pos.c_id
    ,pos.s_type_id
    ,pos.s_type
    ,pos.e_date
    ,pos.mv
    ,0 is_pub
    , 1 is_adj           
    ,pos.is_unsup
    ,getdate() date
    ,getdate() timestamp
    from #temp pos
    left join acc c with(nolock) ON pos._id = c.c_id
    AND pos.account_id = c.account_id
    AND pos.Pr_id = c.pr_id
    AND pos.prog_id = c.prog_id
    AND pos.port_id = c.port_id
    and pos.style_type_id=c.s_type_id
    AND pos.s_id = c._id
    AND pos.c_id = c.c_id
    AND pos.s_type = c.s_type
    AND pos.is_unsup = c.is_uns
    AND pos.is_pub = 1
    where c.a_id is null
union all
 select pos.C_id
    ,pos.s_id
    ,pos.A_id
    ,pos.Ad_id
    ,pos.Pr_id
    ,pos.prog_id
    ,pos.port_id
    ,pos.o_type
    ,pos.o_id
    ,pos.s_id
    ,pos.c_id
    ,pos.s_type_id
    ,pos.s_type
    ,pos.e_date
    ,pos.mv
    ,0 is_pub
    , 1 is_adj           
    ,pos.is_unsup
    ,getdate() date
    ,getdate() timestamp
    from #temp pos
    left join acc c with(nolock) ON pos._id = c.c_id
    AND pos.account_id = c.account_id
    AND pos.s_id = c._id
    AND pos.c_id = c.c_id
    AND pos.s_type = c.s_type
    AND pos.is_unsup = c.is_uns
    AND pos.is_pub = 1
    where c.a_id is null
    AND pos.Pr_id is null AND  c.pr_id is null
    AND pos.prog_id is null AND  c.prog_id is null
    AND pos.port_id is null AND  c.port_id is null
    and pos.style_type_id is null AND c.s_type_id is null

【讨论】:

    【解决方案2】:

    尝试使用

    AND (pos.Pr_id = c.pr_id OR (pos.Pr_id IS NULL AND c.pr_id IS NULL))
    

    而不是

    AND ISNULL(pos.Pr_id,0) = ISNULL(c.pr_id,0)
    

    IS NULL 比 ISNULL 更有效

    【讨论】:

      【解决方案3】:

      您确实需要在临时表#temp 上设置聚集索引,如果不存在,sql-server 将为连接提供默认的基于散列的索引,它对于大型表不适用。

      如果您在 #temp 表中拥有的所有 id 列中的任何一个是唯一键,您确实需要在其上创建聚集索引:

      CREATE CLUSTERED INDEX cx_temp ON #temp (YourIDColumn);
      

      如果您在#temp 中没有键列,请以这种方式为其添加身份主键:

      1)如果你使用SELECT INTO的方式创建#temp,改变

      select *
      into #temp
      from YourQuery
      

      在

      select IDENTITY (int, 1,1) ThisIsTheKey, *
      into #temp
      from YourQuery
      
      -- and then add the index
      CREATE CLUSTERED INDEX cx_temp ON #temp (ThisIsTheKey);
      

      1) 如果您使用CREATE TABLE + INSERT INTO 方法,只需像这样添加列:

      CREATE TABLE #TEMP (
          ThisIsTheKey INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
          ..
          ..
          -- ALL YOUR OTHER COLUMNS
          ..
          ..
      )
      

      不要依赖覆盖非聚集索引,因为您选择的列太多,优化器可能不会使用它们。

      首先测试聚集索引,如果需要进一步优化可以尝试添加一些特定的非聚集索引。

      【讨论】:

        猜你喜欢
        • 2016-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-22
        • 2016-08-03
        相关资源
        最近更新 更多