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

Pur*_*ome 5 sql sql-server performance sql-server-2008

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

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

GEOGRAPHY第3个表中的那些字段..它们不应该与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
Run Code Online (Sandbox Code Playgroud)

替代文字

替代文字

替代文字

替代文字

更新

根据要求,这里有一些关于GeographyBoundaries表的更多信息...... 替代文字

/****** 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
Run Code Online (Sandbox Code Playgroud)

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

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

替代文字

什么Zee Frak?

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

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

  • 确保MyUSALocations表没有使用Joins搞砸了.
  • 确保PK做的很奇怪.

.

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

Ali*_*tad 4

这是不对的。

我有两种可能性:

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

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

更新

我很高兴它奏效了。现在一些解释。

首先,如果某些事情不太正确并且执行计划看起来很奇怪,请始终查看统计信息并重建索引。

为聚集索引创建非聚集索引通常不会带来任何好处,但是当表有很多记录并且记录接近其 8K 限制时,它会很有帮助。正如你所知,SQL 当它去磁盘加载一条记录时,它会加载一个 8K 的页面。以类似的方式访问索引,它将加载 8K 页面。现在,索引是 4 字节整数,这意味着加载 2000 条记录的 ID,而如果使用聚集索引,它将加载少量记录(请记住,我们需要的只是 JOIN 位的 ID)。现在这是一个二分搜索,我不希望它有很大的帮助。所以也许还有其他地方不太正确,但在没有看到系统的情况下很难猜测。