在这种情况下如何将索引扫描更改为索引查找?

时间:2017-03-14 11:52:51

标签: sql-server performance indexing

我在sql server 2008 r2上有以下查询:

IF OBJECT_ID('tempdb..#temp') IS NOT NULL
  /*Then it exists*/
  DROP TABLE #temp
Select *
FROM
      openquery(mysqlserver, 'select
id,street,name,customer,customerId
from table1                     as t1
    left join table2    as t2 
        on t2.id=t1.id
    left join table3    as t3
        on t3.id=t1.id
    left join table4    as t4
        on t4.id=t1.producto_id
    left join table5            as t5
        on t1.id = t5.id
where t1.type=0 
    and t3.service=''X''
    and t1.check is null 
    and t1.date > date_sub(CURDATE(),INTERVAL 5 DAY)
    ') 

    SELECT * FROM #temp as t
    left join View as v on v.customerId=t.customerId collate
    SQL_Latin1_General_CP1_CI_AI

上述声明显示了一个执行计划,其中索引扫描成本为27%,另一个成本为26%。这与视图中其中一个表中的左连接操作有关。

我想在temp表中添加索引:

    CREATE NONCLUSTERED INDEX ix_temp_customerId on #temp(customerId)

它仍然相同,所以我尝试在创建索引之前应用整理:

ALTER TABLE #temp alter COLUMN customerId varchar(30) collate SQL_Latin1_General_CP1_CI_AI

然后第一个语句的最后一个查询是:

SELECT * FROM #temp as t
        left join View as v on v.customerId=t.customerId

尽管视图使用了此排序规则,但仍显示排序规则错误,并且视图查询中的表使用此排序规则。然后我再次将collat​​e语句添加到查询中。

目前的陈述是:

Select *
    FROM
          openquery(mysqlserver, 'select
    id,street,name,customer,customerId
    from table1                     as t1
        left join table2    as t2 
            on t2.id=t1.id
        left join table3    as t3
            on t3.id=t1.id
        left join table4    as t4
            on t4.id=t1.producto_id
        left join table5            as t5
            on t1.id = t5.id
    where t1.type=0 
        and t3.service=''X''
        and t1.check is null 
        and t1.date > date_sub(CURDATE(),INTERVAL 5 DAY)
        ') 
ALTER TABLE #temp alter COLUMN customerId varchar(30) collate SQL_Latin1_General_CP1_CI_AI

CREATE NONCLUSTERED INDEX ix_temp_customerId on #temp(customerId)

        SELECT * FROM #temp as t
        left join View as v on v.customerId=t.customerId collate
        SQL_Latin1_General_CP1_CI_AI

此执行计划仍显示存在索引扫描。我想把它改成索引寻求,但我没有实现。

有什么建议可以达到更好的表现吗?

谢谢

1 个答案:

答案 0 :(得分:2)

使用Paste The Plan @ brentozar.com分享您的执行计划以下是说明:How to Use Paste the Plan

我会尝试使用正确的数据类型,大小和排序规则显式创建#temp表(将customerId的大小与varchar() View.customerId的{​​{1}}大小相匹配)。

我还会考虑在索引中包含列,因为您使用的是select *

create table #temp (
    id int 
  , street varchar(128) collate SQL_Latin1_General_CP1_CI_AI
  , name varchar(128) collate SQL_Latin1_General_CP1_CI_AI
  , customer varchar(128) collate SQL_Latin1_General_CP1_CI_AI
  , customerId varchar(30) collate SQL_Latin1_General_CP1_CI_AI
  );

insert into #temp
select *
from openquery(mysqlserver, '
  select
    id,street,name,customer,customerId
  from table1           as t1
    left join table2    as t2 
      on t2.id=t1.id
    left join table3    as t3
      on t3.id=t1.id
    left join table4    as t4
      on t4.id=t1.producto_id
    left join table5    as t5
      on t1.id = t5.id
  where t1.type=0 
    and t3.service=''X''
    and t1.check is null 
    and t1.date > date_sub(CURDATE(),INTERVAL 5 DAY)
        ') 

create nonclustered index ix_temp_customerId 
  on #temp(customerId)
    include (id, street, name, customer);

select * 
from #temp as t
  left join View as v 
    on v.customerId=t.customerId