是什么促使SQL Server对返回6000多个行的查询使用不太理想的执行计划? 对于返回所有行的情况,我需要提高查询性能。

我选择所有字段,并在索引中包含的相同三列上添加等级。 根据返回的行数,查询有两个不同的执行计划,因此执行分别需要0.2s或3s。

从1行返回到大约 5000个查询运行速度很快。 从总共返回的6000行中,查询运行缓慢。

Table1具有约。 38000行。 数据库在Azure SQL v12上运行。

表:

CREATE TABLE [dbo].[Table1](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [KOD_ID] [int] NULL,
    [SYM] [nvarchar](20) NULL,
    [AN] [nvarchar](35) NULL,
    [A] [nvarchar](10) NULL,
    [B] [nvarchar](2) NULL,
    [C] [datetime] NULL,
    [D] [datetime] NULL,
 CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
GO

CREATE NONCLUSTERED INDEX [IX_Table1] ON [dbo].[Table1]
(
    [KOD_ID] ASC,
    [SYM] ASC,
    [AN] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
GO

查询:

SELECT TOP 6000 *, RANK() OVER(ORDER BY KOD_ID ASC, SYM ASC, AN ASC) AS Rank#
FROM [dbo].[Table1]

SELECT TOP 7000 *, RANK() OVER(ORDER BY KOD_ID ASC, SYM ASC, AN ASC) AS Rank#
FROM [dbo].[Table1]

两个查询的执行计划

执行计划

===============>>#1 票数:2 已采纳

CREATE NONCLUSTERED INDEX [IX_Table1] ON [dbo].[Table1]
(
    [KOD_ID] ASC,
    [SYM] ASC,
    [AN] ASC
) INCLUDE ([A], [B], [C], [D]);

创建这样的覆盖索引,它应该扫描该索引,甚至很可能不需要排序,因为它的数据已经在索引中排序了。

您的查询重点是:

  1. 第一个计划有一个键查找,请尽可能避免使用键查找(键查找是每行的附加扫描,因为索引没有索引)创建包含INCLUDED列的覆盖索引
  2. 也避免使用排序操作,因为它们对SQL Server而言代价高昂

如果您对索引重建KOD_ID ,并且KOD_ID考虑插入而不是插入,那么考虑到并且KOD_IDSYMAN不能为空,这些可以是表的替代DDL:

如果需要ID以确保唯一性:

CREATE TABLE [dbo].[Table1] (
    [KOD_ID] [int] NOT NULL
    , [SYM] [nvarchar](20) NOT NULL
    , [AN] [nvarchar](35) NOT NULL
    , [ID] [int] IDENTITY(1, 1) NOT NULL
    , [A] [nvarchar](10) NULL
    , [B] [nvarchar](2) NULL
    , [C] [datetime2] NULL
    , [D] [datetime2] NULL
    , CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED ([KOD_ID], [SYM], [AN], [ID])
    );
GO

如果不需要ID以确保唯一性:

CREATE TABLE [dbo].[Table1] (
    [KOD_ID] [int] NOT NULL
    , [SYM] [nvarchar](20) NOT NULL
    , [AN] [nvarchar](35) NOT NULL
    , [A] [nvarchar](10) NULL
    , [B] [nvarchar](2) NULL
    , [C] [datetime2] NULL
    , [D] [datetime2] NULL
    , CONSTRAINT [PK_Table1] PRIMARY KEY CLUSTERED ([KOD_ID], [SYM], [AN])
    );
GO

另外,请注意,我使用datetime2而不是datetime ,这是Microsoft建议的方式: https : //docs.microsoft.com/zh-cn/sql/t-sql/data-types/datetime-transact-sql

timedatedatetime2datetimeoffset数据类型用于新工作。 这些类型符合SQL标准。 它们更便携。 timedatetime2datetimeoffset提供更多秒精度。 datetimeoffset为全局部署的应用程序提供时区支持。

  ask by Megrez7 translate from so

未解决问题?本站智能推荐:

1回复

SQL Server - 条件语句的查询执行计划

条件语句(如IF ... ELSE )如何影响SQL Server(2005及更高版本)中的查询执行计划? 条件语句是否会导致执行计划不佳,在考虑性能时是否需要警惕任何形式的条件? **编辑添加**: 我特指的是缓存的查询执行计划。 例如,在下面的实例中缓存查询执行计划时,是
1回复

查询执行计划:缺少索引

alt text http://img502.imageshack.us/img502/7245/75088152.jpg 我将两个表连接在一起,其中一个是临时表,我在创建表后创建索引。 但是在上面的查询执行计划中说。 我应该考虑将所有扫描操作转换为搜索操作? 有些部分是连接和条
12回复

如何获得查询执行计划?

在Microsoft SQL Server中,如何获取查询/存储过程的查询执行计划?
1回复

如何在SQL Server 2005/2008中清除查询执行统计信息

基于使用从这篇文章获得的这个非常有用的SQL获取查询执行统计信息最常执行的存储过程 - 堆栈溢出 : 我如何完全清除这些执行统计信息并从头开始? 这将特别有用,因为开发错误和测试已经导致例程被调用通常很多次,从而无视真实的使用级别。
2回复

重新设计数据库以减少查询执行时间[SQL Server Express]

我有下表: 该表大约有80万行。 我有一个IP地址作为输入,我试图找出它属于哪个网络。 我尝试了很多方法。 方法一: 我将表的结构转换为: 并编写了一个存储过程以查明一个IP地址是否在2个ip地址之间,然后编写了另一个存储过程,该存储过程使用CURSOR来
4回复

使用TOP和ESCAPE更改查询计划和执行时间

其中一个查询(如下所示)需要90秒以上才能执行。 它从一个相当大的表LogMessage返回~500行。 如果从查询中删除ESCAPE N'~' ,它将在几秒钟内执行。 同样,如果删除了TOP (1000) ,它会在几秒钟内执行。 查询计划在第一种情况下显示Key Lookup (Clu
4回复

SQL Server:比较索引性能

如何使用查询分析器比较表上索引的性能? 我想两次通过“估计执行计划”运行相同的查询,一次使用索引,一次不使用索引,并且对生成的表扫描/索引扫描进行很好的比较。 我已经尝试了CREATE INDEX ...,SELECT ...,DROP INDEX ...,SELECT。 我希望第
1回复

SQL Server查询行为

vw_project是一个包含20个CTE的视图,多次连接它们并返回56列 这些CTE中有许多是自联接的(经典的“每组最后一行”,在我们的案例中,我们获得每个项目的最后相关对象产品/客户/经理) 涉及的大多数表(也许是40个)不超过1000行,视图本身返回634行。 我们正在努
1回复

为什么在查询计划中重复CTE计算,以及如何在不重复代码的情况下对其进行优化?

在此查询的查询计划中,grp_set的计算重复了4次(不同的排序每次花费23%,因此它花费23 * 4 =所有资源的92%): 表err_calc包含约35万条记录,并且按old_db,old_tbl,new_tbl,severity,err,old_col,new_col,old_va
2回复

相同的SQL查询在一个DB中运行所需的时间比在同一服务器下的另一个DB运行的时间长

我有一个SQL数据库服务器和2个数据库,它们具有相同的结构和数据。 我在2个数据库中运行相同的sql查询,其中一个需要更长时间,而另一个在不到50%的时间内完成。 他们都有不同的执行计划。 该视图的查询如下: 我已经尝试的东西是 - 重建和重组表上的索引(tblRRMHistS