标签: execution-plan

如何列出所有强制查询计划并取消一个

使用 SSMS 2016 查询存储,几周前我强制特定查询使用特定计划。现在我时不时地会遇到错误:

由于此查询中定义的提示,查询处理器无法生成查询计划。重新提交查询而不指定任何提示且不使用 SET FORCEPLAN

我假设SET FORCEPLAN是自动传递的,因为执行该查询的代码不会自动传递。所以我想重新审视我的强制计划,也许取消它。但我在查询存储中找不到该查询了。

因此我的问题是:有没有一种方法可以列出所有强制查询计划,然后如何取消一个?

sql-server ssms execution-plan sql-server-2016 query-store

6
推荐指数
1
解决办法
3914
查看次数

为什么第一个执行计划不使用 RowCount Spool?

这是我在SQL Server 2008 R2, 2012,上测试过的复制品2016

第二个和第三个查询确实使用了RowCount Spool,为什么第一个没有?

create table dbo.t (id int identity primary key, v int);
--create statistics ST_t__v on dbo.t(v) with norecompute;

insert into dbo.t (v)
select top (10000) rand(checksum(newid())) * 5
from master.dbo.spt_values a cross join
     master.dbo.spt_values b;
go

declare @v int;

set statistics xml, io on;
select @v = v from dbo.t where exists(select 1 from dbo.t where v = 4);
select @v = v from dbo.t where exists(select …
Run Code Online (Sandbox Code Playgroud)

sql-server optimization execution-plan

6
推荐指数
1
解决办法
207
查看次数

QueryStore 计划强制限制

我有一个DELETE针对带有全文索引列的表运行的语句,cascade启用了一些外键。它看起来像这样:

DELETE FROM dbo.STUDENTS WHERE STUDENTID=@STUDENTID
Run Code Online (Sandbox Code Playgroud)

有时会编译一个计划,其中包括对所有索引操作的非常高的行估计,因此DELETE需要很长时间并导致锁定。

我试图迫使QueryStore一个很好的计划,但是这并不实际工作,表现出last forced plan failure descriptionNO_PLAN

我已确保没有可能使计划无效的架构更改。

查看执行计划,我看到这DELETE涉及到一个包含 FT 索引的系统表的连接:

在此处输入图片说明

加入 FT 索引是否意味着不支持计划强制?

sql-server full-text-search execution-plan sql-server-2016 query-store

6
推荐指数
1
解决办法
291
查看次数

为什么在这个例子中我们有 Top N Sort?

在下面的例子中,结果Index Spool已经排序,为什么我们Top N Sort这里有而不是简单的Top

use tempdb;
go

create table dbo.t1 (id int identity primary key, v int);
create table dbo.t2 (id int identity primary key, v int);

insert into dbo.t1
(v)
select top (1000)
row_number() over (order by 1/0)
from
master.dbo.spt_values a cross join
master.dbo.spt_values b;

insert into dbo.t2
(v)
select top (10000)
row_number() over (order by 1/0) + 10000
from
master.dbo.spt_values a cross join
master.dbo.spt_values b;

set statistics xml, io on;

select
sum(a.v …
Run Code Online (Sandbox Code Playgroud)

sql-server optimization execution-plan

6
推荐指数
1
解决办法
120
查看次数

为什么 ORDER BY NULLS LAST 会影响主键上的查询计划?

使用 PostgreSQL 11,我有下表,大约有 4.5 亿行:

postgres=> \d+ sales
                                                             Table "public.sales"
              Column               |            Type             |             Modifiers              | Storage  | Stats target | Description
-----------------------------------+-----------------------------+------------------------------------+----------+--------------+-------------
 created_terminal_id               | integer                     | not null                           | plain    |              |
 company_id                        | integer                     | not null                           | plain    |              |
 customer_id                       | integer                     |                                    | plain    |              |
 sale_no                           | character varying(20)       | not null                           | extended |              |
 sale_type                         | smallint                    | not null                           | plain    |              |
 source_type                       | smallint                    | not null                           | plain …
Run Code Online (Sandbox Code Playgroud)

postgresql index null order-by execution-plan

6
推荐指数
1
解决办法
442
查看次数

禁用特定视图的顶部 (n) 排序优化

我有一个具有复杂逻辑和三个深度级别(嵌套视图)的视图。由于复杂,我无法粘贴执行计划。

由于视图的目的是向数据分析师提供一些业务分析,而他们正在开发报告时,他们会通过执行选择(前 N 个)查询来检查视图样本。

视图中的这个(前 N 个)查询执行得非常糟糕,因为优化器正在为此视图选择不同的执行计划(afaik CQScanTopSortNew

我尝试对顶部 (N) 用例进行一些优化,例如使用哈希连接,但这会破坏非顶部 (n) 用例。

非顶级 (n) 表现良好。我想知道如何防止优化器在具有 top (n) 子句时选择不同的执行计划,而不会显着改变视图的结构或功能。

例如,如果我在视图中添加一个 select distinct ,优化器总是会选择正确的计划,但视图的功能会发生变化。

sql-server execution-plan sql-server-2016 performance-tuning

6
推荐指数
1
解决办法
299
查看次数

为 WHERE 和 ORDER BY 创建多列索引

我正在尝试创建一个同时在 WHERE 和 ORDER BY 子句中使用的索引。阅读 Postgres 14 文档(11.4.索引和 ORDER BY - https://www.postgresql.org/docs/14/indexes-ordering.html)让我相信:

除了简单地查找查询要返回的行之外,索引还可以按特定的排序顺序传递它们。这允许遵守查询的 ORDER BY 规范,而无需单独的排序步骤。

哇,听起来棒极了,我们来试试吧!我创建了一个测试表,一个包含 WHERE 和 ORDER BY 列的索引,并用数据填充它:

DROP TABLE IF EXISTS testdata;
CREATE TABLE testdata
(
    question_id   TEXT        NOT NULL UNIQUE PRIMARY KEY,
    answerer_id   TEXT        NOT NULL,
    question_date TIMESTAMPTZ NOT NULL,
    answer_date   TIMESTAMPTZ NOT NULL
);

DROP INDEX IF EXISTS idx1;
CREATE INDEX idx1 ON testdata (answerer_id, answer_date, question_date);

TRUNCATE testdata;
INSERT INTO testdata(question_id, answerer_id, question_date, answer_date)
SELECT CONCAT('question_', LPAD(i::TEXT, 4, '0')),
       CONCAT('answerer_', …
Run Code Online (Sandbox Code Playgroud)

postgresql index execution-plan

6
推荐指数
1
解决办法
1225
查看次数

如何通过子查询或连接来利用分区修剪?

我有一个分区表...

CREATE TABLE erco.rtprices
(
    scedtime timestamp with time zone NOT NULL,
    node_id integer NOT NULL,
    lmp numeric(12,6),
    CONSTRAINT rtprices_pkey PRIMARY KEY (scedtime, node_id)
) PARTITION BY LIST (node_id);
Run Code Online (Sandbox Code Playgroud)

每个都有node_id自己的分区。

如果我进行直接查询(第一个版本),例如:

explain select scedtime, lmp 
from erco.rtprices
where node_id = 11111
Run Code Online (Sandbox Code Playgroud)

然后该计划仅对rtprices_11111分区进行顺序扫描。 这就是我要的。

但是,如果我执行(第二个版本)查询,例如

explain select scedtime, lmp 
from erco.rtprices
inner join erco.nodes using (node_id)
where nodename = 'somename'
Run Code Online (Sandbox Code Playgroud)

那么该计划包括对每个分区进行顺序扫描,即使此查询与第一个查询一样有限制。

我尝试了上述查询的另一种形式(第三个版本)。

explain select scedtime, lmp 
from erco.rtprices
where node_id = (select node_id from erco.nodes where nodename='somename') …
Run Code Online (Sandbox Code Playgroud)

postgresql execution-plan partitioning postgresql-performance postgresql-13

6
推荐指数
1
解决办法
1714
查看次数

执行计划中的位图创建导致聚集索引扫描的错误估计

给定 StackOverflow2010 数据库上的以下简单查询:

SELECT  u.DisplayName,
        u.Reputation
FROM    Users u
        JOIN Posts p
            ON u.id = p.OwnerUserId
WHERE   u.DisplayName = 'alex' AND
        p.CreationDate >= '2010-01-01' AND
        p.CreationDate <= '2010-03-01'
Run Code Online (Sandbox Code Playgroud)

我试图理解为什么创建索引

CREATE INDEX IX_CreationDate ON Posts
(
    CreationDate
)
INCLUDE (OwnerUserId)
Run Code Online (Sandbox Code Playgroud)

产生更好的估计Posts.CreationDate

当我运行没有索引的查询时,我得到Plan 1。在此计划中,SQL Server 估计 Posts 上的 CI 扫描产生 298,910 行,实际上返回 552 行 - 这个估计值相差甚远。

添加索引后,我会得到Plan 2,这会导致索引查找和更准确的估计。

我很好奇为什么添加索引会导致更好的估计,因为当在谓词中使用列时会创建统计信息WHERE,无论它是否被索引。

经过进一步检查,我可以看到计划 1 与计划 2 上的谓词Posts.CreationDate不同:

计划 1 谓词

[StackOverflow2010].[dbo].[Posts].[CreationDate] as [p].[CreationDate]>='2010-01-01 00:00:00.000' AND [StackOverflow2010].[dbo].[Posts].[CreationDate] …
Run Code Online (Sandbox Code Playgroud)

sql-server execution-plan database-internals cardinality-estimates sql-server-2019

6
推荐指数
1
解决办法
2317
查看次数

为什么 sys.dm_exec_query_stats 中缺少大多数缓存计划?

我试图了解 SQL Server 2016 SP3 系统上缓存元数据的一些执行计划,但我无法将我所看到的内容与文档相一致。

文档sys.dm_exec_cached_plans说它包含:

SQL Server 缓存每个查询计划的一行,以加快查询执行速度。

在我正在观察的系统上,该视图现在有 41,283 行。其中绝大多数(37,594 行)是cacheobjtype =“Compiled Plan”和objtype =“Adhoc”。

文档sys.dm_exec_query_stats说它包含:

缓存计划中每个查询语句一行,行的生命周期与计划本身相关。当从缓存中删除计划时,相应的行将从该视图中删除。

我预计此视图中至少有 37,594 行(每个缓存计划一个,如果某些缓存计划有多个语句,则可能更多)。但是,该视图总共有 6,867 行。

这种差异是如此之大,以至于我必须假设我误解了这些视图中应该包含的内容。

sys.dm_exec_query_stats有人可以帮助我理解为什么与 相比 的行数如此之少吗sys.dm_exec_cached_plans

我尝试在 上将表内部连接在一起plan_handle,唯一的匹配是 1:1 - 换句话说,有数以万计的缓存计划,没有“查询统计”行。

我还认为差异可能是由sys.dm_exec_procedure_stats或中的许多行来解释的sys.dm_exec_trigger_stats,但事实并非如此(分别为 93 行和 2 行)。

对于任何对这个问题的“为什么”感到好奇的人,我试图查看缓存中的各种计划有多旧,并且我不确定除了加入和sys.dm_exec_query_stats检查之外还有什么方法可以做到这一点creation_time


以下是我用来获取上面引用的数字的查询:

-- total cached plans
SELECT COUNT_BIG(*) AS total_cached_plans
FROM sys.dm_exec_cached_plans decp

-- totals by type
SELECT decp.cacheobjtype, decp.objtype, COUNT_BIG(*) AS plan_count
FROM sys.dm_exec_cached_plans …
Run Code Online (Sandbox Code Playgroud)

sql-server execution-plan plan-cache sql-server-2016

6
推荐指数
1
解决办法
878
查看次数