如何用非聚集索引查找或聚簇索引替换聚簇索引扫描?

时间:2011-07-21 08:52:49

标签: sql-server-2008

下面是我的创建表脚本: -

CREATE TABLE [dbo].[PatientCharts](
[PatientChartId] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
[FacilityId] [uniqueidentifier] NOT NULL,
[VisitNumber] [varchar](200) NOT NULL,
[MRNNumber] [varchar](100) NULL,
[TimeIn] [time](7) NULL,
[TimeOut] [time](7) NULL,
[DateOfService] [date] NULL,
[DateOut] [date] NULL),

我在PatientChartId上有一个聚集索引,在VisitNumber和MRNNumber上有两个非聚集索引。该表有数百万条记录。

以下查询正在进行聚簇索引扫描: -

SELECT  *
FROM    dbo.PatientCharts
INNER JOIN ( SELECT FacilityID
                 FROM   Facilities
                 WHERE  RemoteClientDB IN (
                        SELECT  SiteID
                        FROM    RemoteClient WITH ( NOLOCK )
                        WHERE   Code = 'IN-ESXI-EDISC14'
                                )
               ) AS Filter ON dbo.PatientCharts.FacilityId = Filter.FacilityID   

由于数据量的原因,这种聚集索引扫描在生产中花费了大量时间。

执行计划是: -

enter image description here

我甚至尝试在FacilityID上添加一个非clusted索引并包括PatientChartID但仍然是相同的执行计划。

我每次都在做DBCC FREEPROCCACHE,以指示sql server每次都使用新的计划。

我还有什么其他方法可以阻止聚类索引扫描吗?

4 个答案:

答案 0 :(得分:2)

由于没有索引支持您的查询,因此将发生群集扫描。即使您对FacilityID和PatientChartID进行索引,由于超过临界点(Google Kimberly Tripp Tipping Point),您仍有可能要求扫描足够数量的数据

没有简单的方法可以说下一部分,但是对于一个拥有数百万条记录的系统,但这样一个简单的查询会导致您遇到问题,您将不得不更多地了解索引的一般情况以及如何SQL计划引擎的行为。我会推荐Kalen Delany的SQL Internals,如果你在这里搜索书籍推荐,那么就会有一些很好的建议。

答案 1 :(得分:0)

您是否尝试将此实现为具有内部联接的直接查询,而不是为每个步骤使用子查询?

如果您将查询更改为以下格式,我很乐意看看生成的执行计划:

select * from patientschart...
inner join facilities...
inner join remoteclientdb....
where...

我认为一旦你摆脱了子查询,优化器就会选择正确的索引。试一试并分享执行计划。

另外,另一方面,您是否需要结果集中的所有字段?您可以通过在选择列表中切换到特定列而不是*来获益。

我希望这会有所帮助。

答案 2 :(得分:0)

正如安德鲁所说,你的聚集索引在这里没有帮助你或伤害你 - 如果你没有聚集索引,你会看到一个表扫描(我保证你不会比这更有趣)聚集索引扫描)。

假设这是此表上最重要的查询,我会说您应该更改表设计,以便聚集索引在FacilityID上。那会快得多。

答案 3 :(得分:0)

我认为您应该避免执行SELECT *并指定所需的列。然后,您可以根据您获得的执行计划计划索引