为什么这个Sql语句(带有2个表连接)需要5分钟才能完成?

时间:2010-11-16 00:19:12

标签: sql sql-server performance sql-server-2008

更新:下面添加了3个更新

以下sql语句需要5分钟才能完成。我只是。别。得到。它:( 第一个表中有6861534行。第二个表格略少......第三个表格(包含4个地理字段)与第一个表格相同。

第3个表中的那些GEOGRAPHY字段......它们不应该与sql语句混在一起......应该吗?可能是因为表格太大(由于GEOGRAPHY字段),它有很大的页面大小或某些东西..因此,COUNT会破坏表格扫描吗?

SELECT COUNT(*)
FROM [dbo].[Locations] a
    inner join [dbo].[MyUSALocations] b on a.LocationId = b.LocationId
    inner join [dbo].[GeographyBoundaries] c on a.locationid = c.LocationId

alt text

alt text

alt text

alt text

更新

根据要求,这里有一些关于GeographyBoundaries表的更多信息...... alt text

/****** Object:  Index [PK_GeographyBoundaries]    Script Date: 11/16/2010 12:42:36 ******/
ALTER TABLE [dbo].[GeographyBoundaries] ADD  CONSTRAINT [PK_GeographyBoundaries] PRIMARY KEY CLUSTERED 
(
    [LocationId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO

更新#2 - 添加非聚集索引

之后

添加非聚集索引后,它现在下降到4秒!哪个很棒。但为什么

alt text

Zee Frak是什么?

更新3 - 更有趣和令人困惑的信息!

现在,当我只进行一次加入并强制使用INDEX时,它会回到5分钟。我这样做了

  • 确保MyUSALocations表没有使用连接来解决问题。
  • 确保PK做的很奇怪。

SELECT COUNT(*)
FROM [dbo].[Locations] a 
        INNER JOIN [dbo].[GeographyBoundaries] c
            WITH (INDEX(PK_GeographyBoundaries)) ON a.locationid = c.LocationId

4 个答案:

答案 0 :(得分:4)

这不对。

我有两种可能性:

1)表格上的统计数据已过时。重建索引并更新统计信息。

2)如你所说,地理表记录跨越很多页面(不是一个记录跨越多个页面,因为它不能,但记录接近8K标记)。在这种情况下,有趣的是,在聚簇索引上创建另一个非聚集索引可能有所帮助。

<强>更新

我很高兴它有效。现在解释一下。

首先,如果某些事情确实不对,执行计划看起来很奇怪,那么请始终查看统计数据并重建索引。

为聚簇索引创建非聚集索引通常不应该提供任何好处,但是当表有很多记录并且记录接近其8K限制时,它会很有帮助。如您所知,SQL在进入磁盘加载记录时会加载8K页面。以类似的方式转到索引它将加载8K页面。现在索引是一个4字节的整数,这意味着加载2000条记录的ID,如果它使用聚簇索引,它将加载少量记录(请记住我们所需要的只是JOIN位的ID)。现在这是一个二进制搜索,我不希望它只是一点点帮助。所以也许其他东西不太正确,但很难猜测没有看过系统。

答案 1 :(得分:0)

我不确定没有看到一些数据,但97%的成本是您在GeographyBonudaries表上的聚集索引扫描。 LocationID是GeographyBoundaries表的主键吗?

你可以尝试创建一个只包含locationID的新表,并与它连接而不是GeographyBoundaries表来查看地理字段是否是你的罪魁祸首。只需确保将所有索引设置为相同,以确保将苹果与苹果进行比较。我猜这些领域正在减慢你的速度。

如果这确实加快了速度,并且需要经常进行计数,请考虑保留此新表并定期刷新,具体取决于数据更新的频率以及计数需要的准确性在任何给定的时间点。

出于好奇,PK_GeographyBoundaries的定义是什么?

答案 2 :(得分:0)

我会说大部分工作都是I / O.查询计划似乎表明相对于CPU成本的高I / O成本。例如,在PK_GeographyBoundries上,估计的CPU成本约为7.5,估计的I / O成本约为1730,这是估计运营商成本的很大一部分。

统计信息可能已过时,但似乎并不太有帮助。无论如何它必须扫描整个表格。它可能受益于对非聚集索引的扫描,如果它存储在较少的页面上,但无论如何都有很多I / O.而且,最好的索引是LocationID,它集中在两个表上。你已经获得了最好的指数。

如果提高性能非常重要,那么您必须考虑加速物理I / O的方法。

我不确定地理列是否会影响性能。查询计划显示行大小很小(每个11个字节)。

答案 3 :(得分:0)

嗯,你不需要涉及“位置”表,USA_Loacations和地理边界之间的直接连接将是siffice。优化器已经注意到了这一点,并将loacations表中的因素考虑在内,但如果您直接加入它们,它可能会选择更好的连接策略。