为什么这个Sql语句(有2个表联接)需要5分钟才能完成? 更新:以下添加了3个更新

为什么这个Sql语句(有2个表联接)需要5分钟才能完成? 更新:以下添加了3个更新,sql,sql-server,performance,sql-server-2008,Sql,Sql Server,Performance,Sql Server 2008,下面的sql语句需要5分钟才能完成。我只是。不要。得到。它:( 第一个表中有6861534行。第二个表中有一点少。第三个表(包含4个地理字段)与第一个表相同 第三个表中的GEOGRAPHY字段..它们不应该与sql语句混在一起…是吗?可能是因为表太大(由于GEOGRAPHY字段),它有巨大的页面大小或其他东西..因此破坏了表扫描计数吗 SELECT COUNT(*) FROM [dbo].[Locations] a inner join [dbo].[MyUSALocations] b

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

第三个表中的
GEOGRAPHY
字段..它们不应该与sql语句混在一起…是吗?可能是因为表太大(由于
GEOGRAPHY
字段),它有巨大的页面大小或其他东西..因此破坏了表扫描计数吗

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

更新 根据要求,这里有一些关于GeographyBounders表的更多信息。。。

更新#2-添加非聚集索引后 在添加非聚集索引后,它现在下降到4秒!这太棒了。但是为什么呢

什么Zee Frak

更新3-更有趣和混乱的信息! 现在,当我做一个连接并强制索引时,它会回到5分钟。我这样做是为了

  • 确保MyUSALocations表没有在连接上乱动
  • 确保PK正在做一些奇怪的事情


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

您可以尝试创建一个仅包含locationID的新表,并与其连接,而不是GeographyBordinates表,以查看地理字段是否是您的罪魁祸首。只需确保您将所有索引设置为相同的,以确保您正在对苹果进行比较。我想这些字段会让您速度变慢

如果这确实加快了速度,并且获得计数是你经常需要做的事情,考虑保持这个新表并定期刷新它,这取决于数据被更新的频率和你需要计数在任何给定时间点的准确度。

出于好奇,你的PK_地理边界的定义是什么?

这是不对的

我有两种可能:

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

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

更新

我很高兴它起了作用。现在我来解释一下

首先,如果有些地方不太对劲,执行计划看起来很奇怪,那么总是查看统计数据并重建索引


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

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

这些统计数字可能已经过时了,但似乎并没有太大帮助。无论如何,它必须扫描整个表。如果它存储在更少的页面上,那么它可能会受益于对非聚集索引的扫描,但不管发生什么,您都有大量的I/O。而且,最好的索引是LocationID,它聚集在两个表上。你已经得到了最好的索引

如果提高性能很重要,那么您必须寻找加速物理I/O的方法


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

您不需要涉及“位置”表,可以直接连接美国位置和地理边界。乐观主义者已经注意到了这一点,并考虑了loacations表,但是,如果您直接加入它们,它可能会选择更好的加入策略。

所有LocationId字段都是整数吗?瓦查尔(5000)?其他?GeographyBounders上的索引是否与表数据物理上位于同一文件组上?@Tahbaza:是的,所有Id都是INT。这是一个文件组中的所有文件,或者不管默认标准是什么。我没有对默认的createnewdb做任何调整。我已经根据要求更新了初始帖子,以包含关于geographybundailes表的更多信息。啊,好的。提供的SQL刚刚有count(*)!我需要加入parent Locations表,因为其中有一个字段(名称NVARCHAR(100)),这是我所需要的。总之,我的HD很糟糕,我应该考虑升级?@Pure Krome:可能你的HD不好。要提高I/O性能,可以做两件事:1)减少I/O或2)加快I/O速度。您的更新2似乎显示了#1。非聚集索引执行更少I/O的原因是它占用更少的空间(仅locationID,无地理位置)。扫描更少的页面所需的时间更少。好的,我更新了统计数据,花了32秒。现在我再次运行查询。。。到目前为止只有1分钟,而且还在继续。。所以我不确定这是否有帮助。哥们!WTFFFFFFFFFF!!!!!!!!!!!通过添加新的非聚集索引,现在只需4秒
/****** 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
SELECT COUNT(*)
FROM [dbo].[Locations] a 
        INNER JOIN [dbo].[GeographyBoundaries] c
            WITH (INDEX(PK_GeographyBoundaries)) ON a.locationid = c.LocationId