如何减少简单选择查询的响应时间?

时间:2010-11-19 04:30:19

标签: sql sql-server tsql sql-server-2008

MarketPlane表包含超过6000万行。

当我需要特定日期的飞机总数时,我执行此查询需要超过7分钟。我怎样才能减少这段时间?

SELECT COUNT(primaryKeyColumn) 
FROM   MarketPlan 
WHERE  LaunchDate > @date

我已经实现了链接中提到的所有内容,即使现在我已经实现了With(nolock),这可以将响应时间减少到5分钟。

10 个答案:

答案 0 :(得分:3)

答案 1 :(得分:0)

相关表格是否在LaunchDate列上有索引?另外,你真的想发帖LaunchDate>@date吗?

答案 2 :(得分:0)

假设基于@date的SQL-Server,尽管可以将其应用于大多数数据库。

如果您的主要查询是选择一系列数据(基于样本),添加或更改CLUSTERED INEDX将大大有助于缩短查询时间。

请参阅:http://msdn.microsoft.com/en-us/library/ms190639.aspx

默认情况下,SQL-Server将主键创建为聚簇索引,从事务的角度来看这是很好的,但如果您的重点是检索数据,那么更改默认值会产生巨大的差异。

CREATE CLUSTERED INDEX name ON MarketPlan (LaunchDate DESC)

注意:假设LaunchDate是一个静态日期值,主要以递增/顺序顺序插入,以最小化索引碎片。

答案 3 :(得分:0)

这里有一些很好的建议,如果所有其他方法都失败了,请考虑一点非规范化,创建另一个包含累积计数的表并用触发器更新它。如果您有更多这种性质的疑问,请考虑OLAP

答案 4 :(得分:0)

您的特定查询不需要日期列上的群集密钥。使用带有前导日期列的非聚簇索引实际上会更好地运行,因为您不需要在此查询中执行键查找,因此非聚簇索引将覆盖并且比聚簇更紧凑(它隐式包括聚簇键列)。 如果你正确索引它并且它仍然没有执行它很可能是碎片。在这种情况下,对索引进行碎片整理并重试。

答案 5 :(得分:0)

像这样创建一个新索引:

在MarketPlan上创建INDEX xLaunchDate(LaunchDate,primaryKeyColumn)

查看这篇关于索引如何提高性能的好文章。

http://blog.sqlauthority.com/2009/10/08/sql-server-query-optimization-remove-bookmark-lookup-remove-rid-lookup-remove-key-lookup-part-2/

答案 6 :(得分:0)

  

“WHERE LaunchDate> @date”

参数@date的值是否在同一批次(或事务或上下文)中定义? 如果不是,那么如果其值来自当前批次之外(例如,存储过程的输入参数),则这将导致聚集索引扫描(所有行)而不是聚集索引搜索(仅满足WHERE条件的行)或udf功能) SQL Server优化器(在编译时)无法完全优化查询,导致全表扫描,因为参数值仅在运行时知道

更新:评论提出OLAP的答案 OLAP只是概念,SSAS多维数据集只是OLAP实现的可能方式之一 获取/使用OLAP概念是方便而非义务 您尚未使用SSAS来使用OLAP概念 例如,见Simulated OLAP

更新2:评论评论to answer

MDX是SSAS提供的选项/便利/功能/功能(cube / OLAP)没有义务

答案 7 :(得分:0)

你能做的最简单的事情是:

SELECT COUNT(LaunchDate) 
FROM   MarketPlan 
WHERE  LaunchDate > @date

这将保证您对任何LaunchDate索引的索引检索。

另外(这取决于你的执行计划),我见过实例(但不是特定于SQL Server),其中&gt;做过表扫描,BETWEEN使用了索引。如果您知道最新日期,可以尝试WHERE LaunchDate BETWEEN @date AND <<Literal Date>>

答案 8 :(得分:0)

桌子有多宽?如果表是宽的(即:(n)char,(n)varchar或xml的许多列),可能会有大量的IO导致查询由于使用聚簇索引而运行缓慢。

要确定IO是否导致长查询时间,请执行以下操作:

  1. 仅在LaunchDate列上创建非聚集索引。
  2. 运行下面的查询,计算LaunchDate并强制使用新索引。

    SELECT COUNT(LaunchDate)

    FROM MarketPlan WITH(INDEX = TheNewIndexName)

    WHERE LaunchDate&gt; @date

  3. 我不喜欢使用索引提示,我只建议此提示仅用于证明IO是否导致查询时间过长。

答案 9 :(得分:0)

有两种方法可以做到这一点

  1. 首先在日期列上创建聚簇索引,因为查询是特定于日期范围的,所有数据都将按实际顺序排列,这将避免必须扫描表中的所有记录

    < / LI>
  2. 您可以尝试使用水平分区,这会影响您现有的表设计,但这是最佳方式,请参阅此 http://blog.sqlauthority.com/2008/01/25/sql-server-2005-database-table-partitioning-tutorial-how-to-horizontal-partition-database-table/