【问题标题】:How to change index scan to index seek in this case?在这种情况下如何将索引扫描更改为索引搜索?
【发布时间】:2017-03-14 11:52:51
【问题描述】:

我在 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%。这与视图内的一个表中的左连接操作有关。

我想用这个在临时表中添加索引:

    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

此执行计划仍显示存在索引扫描。我想将其更改为索引搜索,但我没有实现。

有什么提高性能的建议吗?

谢谢

【问题讨论】:

标签: sql-server performance indexing


【解决方案1】:

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

我会尝试使用正确的数据类型、大小和排序规则显式创建您的#temp 表(将customerId 的大小与View.customerIdvarchar() 大小匹配)。

我也会考虑在索引中包含列,因为您使用的是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

【讨论】:

  • 我会试试的,我告诉过你一些事情。
  • 谢谢。我用正确的排序规则创建了表,尽管在左连接中,我必须重新应用排序规则,它在 10 秒内工作。它仍然很慢,但至少不是几分钟。
猜你喜欢
  • 2015-01-24
  • 1970-01-01
  • 2011-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-08
  • 1970-01-01
相关资源
最近更新 更多