我正在尝试优化我的存储过程。当我查看查询计划时,我可以看到tempcompany上的tablescan显示为97%。我还看到以下消息缺少索引(Impact 97):在#tempCompany上创建非聚集索引 我已经设置了非聚集索引。有人可以指出问题是什么
if object_id('tempdb..#tempCompany') is not null drop table #tempCompany else
select
fp.companyId,fp.fiscalYear,fp.fiscalQuarter,fi.financialperiodid, fi.periodEndDate,
fc.currencyId,fp.periodtypeid,ROW_NUMBER() OVER (PARTITION BY fp.companyId,
fp.fiscalYear, fp.fiscalQuarter ORDER BY fi.periodEndDate DESC) rowno
into #tempCompany
from
ciqFinPeriod fp
inner join #companyId c on c.val = fp.companyId
join ciqFinInstance fi on fi.financialperiodid = fp.financialperiodid
join ciqFinInstanceToCollection ic on ic.financialInstanceId = fi.financialInstanceId
left join ciqFinCollection fc on fc.financialCollectionId = ic.financialCollectionId
left join ciqFinCollectionData fd on fd.financialCollectionId = fc.financialCollectionId
where
fp.periodTypeId = @periodtypeId
and fi.periodenddate >= @date
--and fp.companyId in (select val from @companyId)
CREATE NONCLUSTERED INDEX id_companyId2 on #tempCompany(companyId,fiscalYear,fiscalQuarter,financialperiodid,periodEndDate,currencyId,periodtypeid,rowno)
if object_id('tempdb..#EstPeriodTbl') is not null drop table #EstPeriodTbl else
select
companyId,fiscalYear,fiscalQuarter,financialPeriodId,periodenddate,currencyId,
periodtypeid,rowno
into #EstPeriodTbl
from #tempCompany a
where a.rowno = 1
order by companyid, periodenddate
CREATE NONCLUSTERED INDEX id_companyId3 on #EstPeriodTbl(companyId,periodenddate,fiscalYear,fiscalQuarter,currencyId,financialPeriodId,rowno)
Execution Plan
答案 0 :(得分:1)
您无需在 #tempCompany 索引中包含所有内容;只是 rowno :
CREATE NONCLUSTERED INDEX id_companyId2 on #tempCompany(rowno)
答案 1 :(得分:1)
简短回答:您提供的索引在您正在进行的查询中无法帮助SQL Server。如果您创建另一个非聚集索引,并且rowno
作为索引中的第一列,则Sql Server可能会使用该索引。
长期探索: 您遇到问题的原因是因为您创建的索引对于具有此特定查询的SQL Server并不有用。记录在索引上排序的顺序由您在创建索引时指定的顺序确定。
(例如,您的索引首先按照companyId对您的记录进行排序,然后按照其financialYear,然后按其财务季度对同一companyId的记录进行排序。)
尝试使用提供的索引通过它的rowno值来查找项目,就像您尝试根据某人的电话号码查找电话簿中的条目一样。找到所有匹配记录的唯一方法是搜索书中的每个记录(即表扫描)。
通常,只有当您在where子句中使用的信息与索引中的第一列匹配时,您才可以使用非聚簇索引(即,如果您可以在where子句中为companyId提供SARGable谓词,则可以使用此指数)
再次使用电话簿:如果我给你一个姓氏和电话号码,现在你不再需要对电话簿进行全表扫描,你可以对姓氏进行索引扫描。哪个会更有效率。如果您能够提供姓氏和名字,然后是中间的初始和电话号码,您可以进行更高效的表格扫描。但是,如果我只提供姓氏,中间名字和电话号码;现在我回到仅仅使用姓氏的值来扫描索引。
因此,如果您可以缩小记录集以至少使用companyId(即在where子句中使用companyID),则可以使用您提供的索引。
或者,我想这就是你想要做的,创建一个按rowno
,然后companyId
和periodendDate
排序的索引。
e.g。
CREATE NONCLUSTERED INDEX idx_temp_rowno ON #tempCompany(rowno, companyId, periodenddate)