我正在学习执行计划并尝试不同的查询并比较它们的性能并偶然发现了这一点:
SELECT StatisticID
FROM (
SELECT StatisticID, ROW_NUMBER() OVER (ORDER BY StatisticID) AS rn
FROM FTCatalog.Statistic
) AS T
WHERE T.rn <= 1000
ORDER BY rn
SELECT TOP 1000 StatisticID
FROM FTCatalog.Statistic
ORDER BY StatisticID
Run Code Online (Sandbox Code Playgroud)
它们都返回相同的结果集 - 但是第一个执行速度更快并且资源消耗更少(至少 SSMS 告诉我)这是执行计划:

与 SQL 查询计划资源管理器的比较:
谁能给我一些关于幕后实际发生的事情以及结果为何不同的见解?如果您还有什么需要 - 请告诉我。
谢谢,埃瓦尔达斯。
我有一个奇怪的情况。使用sp_whoisactive我可以看到:
好的,通过这个查询,我可以看到是什么触发了(这个词在英语中存在吗?)它:
SELECT c.session_id, c.properties, c.creation_time, c.is_open, t.text
FROM sys.dm_exec_cursors (SPID) c --0 for all cursors running
CROSS APPLY sys.dm_exec_sql_text (c.sql_handle) t
Run Code Online (Sandbox Code Playgroud)
结果:
这是一个简单的select. 为什么要使用 f etch_cursor?
另外,我也看到了很多“空白”的 sql_texts。这与这个“光标”有关系吗?
DBCC INPUTBUFFER (spid) 给我看这个:
有这个问题 在这里(我做的),但我不知道这是否是同样的事情。
编辑1:
使用 kin 提供的查询,我看到了这一点:
编辑2:
使用活动监视器,我可以看到:
这是最昂贵的查询(第一个是故意的,我们知道)。
再一次,我想知道,为什么这select * from...是FETCH CURSOR……的原因。
编辑3:
这个“ select * from...”是从另一台服务器(通过linked server)运行的。
好吧,现在我无法理解@kin 所说的内容。
这是execution plan查询的(在数据库的同一服务器中运行):
这是现在,通过链接服务器在另一台服务器上运行的执行计划:
好的,也不是问题。现在!执行计划,通过**activity monitor**(相同select * from):
我读过的任何地方都说估计操作员成本是估计 CPU 成本和估计 I/O 成本的总和。但是,在我看到的许多运营商中,情况并非如此。下面是一个例子:
SELECT Column2
INTO Object1
FROM Object2
WHERE Column3 >= Variable2
AND Column3 <= Variable1
AND ( Column4 = Variable5
OR Variable5 = ? )
Run Code Online (Sandbox Code Playgroud)
EstimateIO="0.01" EstimateCPU="0.000246492"
总和:0.010246492
然而,SSMS 将此 0.073823 显示为估计的运营商成本。我完全不知道这是如何计算的。下面是执行计划 xml(匿名)。Node Id 0 是有问题的节点。
<?xml version="1.0" encoding="utf-16"?>
<ShowPlanXML xmlns="http://schemas.microsoft.com/sqlserver/2004/07/showplan" Version="1.2" Build="11.0.6537.0">
<BatchSequence>
<Batch>
<Statements>
<StmtSimple StatementText="	SELECT Column2 INTO Object1 
	FROM Object2
	WHERE Column3>=Variable2 AND Column3<=Variable1 
	AND (Column4=Variable5 OR Variable5=?)

" StatementId="1" StatementCompId="7" StatementType="SELECT INTO" RetrievedFromCache="true" StatementSubTreeCost="0.405134" StatementEstRows="246.492" StatementOptmLevel="FULL" QueryHash="0x180DF38DFFFEAFA2" QueryPlanHash="0x45A4295471B90968" StatementOptmEarlyAbortReason="GoodEnoughPlanFound">
<StatementSetOptions QUOTED_IDENTIFIER="true" ARITHABORT="false" CONCAT_NULL_YIELDS_NULL="true" ANSI_NULLS="true" …Run Code Online (Sandbox Code Playgroud) 由于特定查询使用了错误的执行计划,我遇到了 100% CPU 峰值的大问题。我现在花了几个星期自己解决。
我的示例数据库包含 3 个简化表。
CREATE TABLE [model].[DataLogger](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[ProjectID] [bigint] NULL,
CONSTRAINT [PK_DataLogger] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)
CREATE TABLE [model].[Inverter](
[ID] [bigint] IDENTITY(1,1) NOT NULL,
[SerialNumber] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Inverter] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY],
CONSTRAINT [UK_Inverter] UNIQUE NONCLUSTERED
(
[DataLoggerID] ASC,
[SerialNumber] ASC
)WITH …Run Code Online (Sandbox Code Playgroud) performance execution-plan sql-server-2016 query-performance
我读到只有Trivial Plans 可以是 Simple Parameterized,并且并非所有查询(即使计划是 Trivial )都可以是 Simple Parameterized。
那么为什么这个计划同时显示了全面优化和简单参数化?
sql-server execution-plan trivial-plan simple-parameterization
我正在解决与 SQL Server(技术上是 Azure SQL 数据库)相关的问题,偶尔会选择错误的执行计划,大概是由于统计数据不准确。sp_updatestats每次都修复它,直到几个小时或几天后,一个糟糕的计划再次被缓存。
看着“糟糕”的计划,我注意到一些让我感到奇怪的事情:在当前大约有 170 万行的表上有一个聚集索引查找。此操作的“估计行数”约为 1200,这绝对符合我在这种情况下对该操作所期望的平均行数,但“实际行数”超过 6000 万!沿着这个叶节点的粗线,在所有 6000 万个节点上执行各种下游操作,例如连接和排序,导致过慢、溢出到 tempdb 和其他坏处。
我一定误解了聚集索引查找实际上是做什么的,因为我认为它不可能“输出”比基础表中更多的行。什么可能导致这种情况?更好的是,有关如何修复它的任何指示?
[包含诸如“sp_updatestats每次修复它但无法弄清楚如何永久修复它?阅读这篇文章”之类的奖励积分。这是我们最近在几个不同方面的普遍问题。]
我目前正在设计一个事务表。我意识到需要计算每一行的运行总数,这可能会降低性能。所以我创建了一个包含 100 万行的表用于测试。
CREATE TABLE [dbo].[Table_1](
[seq] [int] IDENTITY(1,1) NOT NULL,
[value] [bigint] NOT NULL,
CONSTRAINT [PK_Table_1] PRIMARY KEY CLUSTERED
(
[seq] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Run Code Online (Sandbox Code Playgroud)
我试图获取最近的 10 行及其运行总数,但花了大约 10 秒。
--1st attempt
SELECT TOP 10 seq
,value
,sum(value) OVER (ORDER BY seq) total
FROM Table_1
ORDER BY seq DESC
--(10 rows affected)
--Table 'Worktable'. Scan count 1000001, logical reads 8461526, …Run Code Online (Sandbox Code Playgroud) performance database-design sql-server t-sql execution-plan query-performance
我对为什么我的查询没有使用我认为是选择性索引的东西感到非常困惑。
我的模型由索赔、联系人和电话号码组成。每个索赔有 1 个联系人,每个联系人都有许多电话号码。索赔可以有状态,电话号码有类型。

我在状态的 Claim 上添加了一个索引,它包括 ContactID。
create index Status on tClaim(Status) include (Name,ContactID)
Run Code Online (Sandbox Code Playgroud)
我在电话上为 ContactID 和类型添加了一个索引,其中包括号码。
create index ContactID_Type on tContactPhone(ContactID,Type) include (Number)
Run Code Online (Sandbox Code Playgroud)
我正在尝试编写一个查询,该查询返回状态为“赢得”的所有索赔以及索赔联系人的相应“家庭电话”。我已经尝试了 2 种方法。一种包括加入通讯录,另一种没有。两者都不会产生我期望的计划。
select
c.ID,
c.Name,
p.Number
from
tClaim c
left join tContactPhone p on
c.ContactID=p.ContactID and p.Type='Home'
where
c.Status = 'Won'
select
c.ID,
c.Name,
p.Number
from
tClaim c
inner join tContact co on
co.id=c.ContactID
left join tContactPhone p on
co.ID=p.ContactID and p.Type='Home'
where
c.Status = 'Won'
Run Code Online (Sandbox Code Playgroud)
我回来的计划拒绝使用 tContactPhone.ContactID_Type。它建议按类型索引,这没有意义,因为它似乎没有 ContactId 选择性。
这是我用来创建要测试的示例数据集的脚本。请注意我的实际数据集要大得多,命名得更好,并且有更多的字段;但这被提炼出来以复制我的情况 [AKA 我什至不喜欢命名约定和数据生成,但它完成了工作:)] …
index sql-server execution-plan cardinality-estimates sql-server-2019
我有一个 SQL 查询,它是由一堆嵌套的视图和表值函数组成的,深度至少为 4 层(我没有时间或耐心去完成这一切,它有数百行代码在每个级别)。
我一直试图理解为什么当我使用选项(重新编译)运行基本查询时它运行得非常快,但是当我在没有这个选项的情况下运行它时,它运行得非常慢。
我已确保在发生这种情况之前清除计划缓存,即使在生成新计划时,它也不是最佳的,但是,选项(重新编译)速度很快。
我检查了这两个计划,并注意到对于带有选项(重新编译)的计划,传递的参数。
SELECT [p].[Activity]
,[p].[ActivityType]
,[p].[Company]
,[p].[Flags]
,[p].[Id]
,[p].[Name]
,[p].[Priority]
,[p].[Filters]
,[p].[Priority]
,[p].[Classification]
,[p].[Number]
,[p].[TaskFilter]
,[p].[TaskType]
,[p].[User]
FROM (
SELECT *
FROM [ActivProdStatuses]('ProdJobTask', 0)
) AS [p]
WHERE (
( ([p].[User] = 'some_value') AND (([p].[Flags] & 8) = 0) )
AND ([p].[Activity] = 'unique_value')
)
AND
(CASE
WHEN ([p].[Flags] & 4) <> 0
THEN CAST(1 AS BIT)
ELSE CAST(0 AS BIT)
END = 1 )
ORDER BY [p].[Priority]
OPTION (RECOMPILE)
Run Code Online (Sandbox Code Playgroud)
在没有 OPTION …
sql-server execution-plan azure-sql-database recompile query-performance
execution-plan ×10
sql-server ×8
performance ×3
cursors ×1
index ×1
optimization ×1
process ×1
recompile ×1
ssms ×1
t-sql ×1
trivial-plan ×1