如何减少简单选择查询的响应时间?
Posted
技术标签:
【中文标题】如何减少简单选择查询的响应时间?【英文标题】:How to decrease response time of a simple select query? 【发布时间】:2010-11-19 04:30:18 【问题描述】:MarketPlane
表包含超过 6000 万行。
当我需要特定日期的飞机总数时,我执行这个查询需要 7 分钟以上。我怎样才能减少这个时间?
SELECT COUNT(primaryKeyColumn)
FROM MarketPlan
WHERE LaunchDate > @date
我已经实现了您链接中提到的所有内容,即使现在我已经实现了With(nolock)
,它将响应时间缩短到 5 分钟。
【问题讨论】:
Sql Server 2008 和 LaunchDate 上的集群索引 如果您在 LaunchDate 已经有一个聚集索引,您不应该看到 7 分钟以上的查询时间吗?您一次检索多少条记录? @OMG - 为什么 DateTime 列上的聚集索引不能提高性能?该查询是一个范围扫描,允许快速范围索引查找,因为所有数据都在顺序块中?半相关...msdn.microsoft.com/en-us/library/ms177416.aspx 6000 万条记录也进入了数据所在磁盘的设置可以产生相当大差异的地步。随着数据库的增长,它的优化会涉及更多。 launchDate 的数据类型是 Sql Server 2008 中的日期。 【参考方案1】:你必须在桌子上create an index,或者可能是partition the table 按日期。
你可能还想看看
SQL Server 2000/2005 Indexed View Performance Tuning and Optimization Tips
SQL Server Indexed Views
【讨论】:
它提供了很多信息,但在我的场景中不起作用,因为我已经实现了链接中提到的所有内容。【参考方案2】:有问题的表在LaunchDate
列上有索引吗?还有,你真的是想发LaunchDate>@date
吗?
【讨论】:
【参考方案3】:假设 SQL-Server 基于@date,虽然同样可以应用于大多数数据库。
如果您的主要查询是选择一系列数据(基于样本),添加或更改 CLUSTERED INEDX 将大大缩短查询时间。
见:http://msdn.microsoft.com/en-us/library/ms190639.aspx
默认情况下,SQL-Server 将主键创建为聚集索引,这从事务的角度来看非常棒,但如果您的重点是检索数据,那么更改该默认值会产生巨大的影响。
CREATE CLUSTERED INDEX name ON MarketPlan (LaunchDate DESC)
注意:假设 LaunchDate 是一个静态日期值,并且主要以递增/顺序插入以最大程度地减少索引碎片。
【讨论】:
Topic starter 在他对主帖的第一条评论中写道,他在 LaunchDate 列上有聚集索引 @vgv8 - 是的,这个细节是事后添加的。【参考方案4】:这里有一些很好的建议,如果所有其他方法都失败了,请考虑进行一些非规范化,使用累积计数创建另一个表并使用触发器更新它。如果您有更多这种性质的查询,请考虑 OLAP
【讨论】:
我不想使用 OLAP,因为在它上面我必须编写 MDX 查询来获取数据,并且每次插入新记录时我都必须处理多维数据集。这是我不想要的。 @Jeevan Bhatt,你的两个陈述都是错误的。在Cube中可以进行SQL和实时(ROLAP模式,见***.com/questions/3950948/…)处理 @vg8- 是的,ROLAP 中有实时处理,但你不认为因此我必须使用 MDX 吗? @Jeevan Bhatt,多维数据集中的 MDX 只是一种方便。你可以在那里使用 SQL SQL 可以在 ROLAP 中使用,因为所有数据和元数据都存储在关系源数据库中。 SSAS 仅用于处理而不进行部署。默认 MOLAP 只能使用 MDX【参考方案5】:您的特定查询不需要日期列上的聚集键。它实际上会在带有前导日期列的非聚集索引中运行得更好,因为您不需要在此查询中进行键查找,因此非聚集索引将比聚集索引更紧凑(它隐式包含聚集键列)。 如果您对其进行了正确索引,但它仍然无法执行,则很可能是碎片。在这种情况下,请整理索引并重试。
【讨论】:
Vaso 是正确的。读取非聚集索引的总 IO 小于读取聚集索引。【参考方案6】:像这样创建一个新索引:
在 MarketPlan 上创建索引 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/
【讨论】:
当集群索引在 LaunchDate 时,这并不成立,正如主题启动者在他的第一条评论中所写的那样。【参考方案7】:"WHERE LaunchDate > @date"
参数@date的值是否在同一个批次(或事务或上下文)中定义? 如果不是,那么这将导致聚集索引扫描(所有行)而不是聚集索引搜索(仅满足 WHERE 条件的行),如果它的值来自当前批处理之外(例如,存储过程的输入参数或 udf 函数)。 SQL Server 优化器(在编译时)无法完全优化查询,从而导致全表扫描,因为参数的值仅在运行时才知道
更新:评论提出 OLAP 的答案。 OLAP 只是概念,SSAS 多维数据集只是 OLAP 实现的可能方式之一。 获取/使用 OLAP 概念是方便,而不是义务。 您还没有使用 SSAS 来使用 OLAP 概念。 参见,例如,Simulated OLAP
Update2:在 cmets to answer 中评论问题:
MDX performance vs. T-SQLMDX 是 SSAS(多维数据集/OLAP)提供的选项/便利/特性/功能,不是义务
【讨论】:
【参考方案8】:您可以做的最简单的事情是:
SELECT COUNT(LaunchDate)
FROM MarketPlan
WHERE LaunchDate > @date
这将保证您对任何 LaunchDate 索引进行仅索引检索。
另外(这取决于您的执行计划),我看到了实例(但不是特定于 SQL Server),其中 > 进行了表扫描并且 BETWEEN 使用了索引。如果你知道最晚日期,你可以试试WHERE LaunchDate BETWEEN @date AND <<Literal Date>>
。
【讨论】:
如果唯一的索引聚集在 LaunchDate 列上,那么 "SELECT COUNT(LaunchDate)"、"SELECT COUNT(primaryKeyColumn)" 或 "SELECT COUNT(*)" 之间没有区别,因为这根据“WHERE”条件提取后已应用子句(计数)。 IE。 “WHERE LaunchDate > @date”无法选择具有 NULL LaunchDate 的行,并且 primaryKeyColumn 不能包含 NULL【参考方案9】:桌子有多宽?如果表很宽(即:许多 (n)char、(n)varchar 或 xml 列),则可能有大量 IO 导致查询由于使用聚集索引而运行缓慢。
要确定 IO 是否导致查询时间过长,请执行以下操作:
-
仅在 LaunchDate 列上创建非聚集索引。
运行下面的查询,计算 LaunchDate 并强制使用新索引。
选择计数(启动日期)
来自 MarketPlan WITH (INDEX = TheNewIndexName)
WHERE LaunchDate > @date
我不喜欢使用索引提示,我建议这个提示只是为了证明 IO 是否导致查询时间过长。
【讨论】:
除了 IO 之外,还有什么会导致对 7000 万行表的查询时间过长? vgv8 - 在我发帖时,该问题被标记为已回答。我的条目是添加另一个我认为没有明确包含在其他帖子中的点。【参考方案10】:有两种方法可以做到这一点
首先在日期列上创建一个聚集索引,由于查询是特定于日期范围的,所有数据都将按照实际顺序排列,这样可以避免扫描表中的所有记录
您可以尝试使用水平分区,这会影响您现有的表格设计,但这是最好的方法,请参阅此 http://blog.sqlauthority.com/2008/01/25/sql-server-2005-database-table-partitioning-tutorial-how-to-horizontal-partition-database-table/
【讨论】:
以上是关于如何减少简单选择查询的响应时间?的主要内容,如果未能解决你的问题,请参考以下文章