使用 SSMS 2016 查询存储,几周前我强制特定查询使用特定计划。现在我时不时地会遇到错误:
由于此查询中定义的提示,查询处理器无法生成查询计划。重新提交查询而不指定任何提示且不使用 SET FORCEPLAN
我假设SET FORCEPLAN是自动传递的,因为执行该查询的代码不会自动传递。所以我想重新审视我的强制计划,也许取消它。但我在查询存储中找不到该查询了。
因此我的问题是:有没有一种方法可以列出所有强制查询计划,然后如何取消一个?
这是我在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) 我有一个DELETE针对带有全文索引列的表运行的语句,cascade启用了一些外键。它看起来像这样:
DELETE FROM dbo.STUDENTS WHERE STUDENTID=@STUDENTID
Run Code Online (Sandbox Code Playgroud)
有时会编译一个计划,其中包括对所有索引操作的非常高的行估计,因此DELETE需要很长时间并导致锁定。
我试图迫使QueryStore一个很好的计划,但是这并不实际工作,表现出last forced plan failure description的NO_PLAN。
我已确保没有可能使计划无效的架构更改。
查看执行计划,我看到这DELETE涉及到一个包含 FT 索引的系统表的连接:
加入 FT 索引是否意味着不支持计划强制?
sql-server full-text-search execution-plan sql-server-2016 query-store
在下面的例子中,结果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) 使用 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) 我有一个具有复杂逻辑和三个深度级别(嵌套视图)的视图。由于复杂,我无法粘贴执行计划。
由于视图的目的是向数据分析师提供一些业务分析,而他们正在开发报告时,他们会通过执行选择(前 N 个)查询来检查视图样本。
视图中的这个(前 N 个)查询执行得非常糟糕,因为优化器正在为此视图选择不同的执行计划(afaik CQScanTopSortNew)
我尝试对顶部 (N) 用例进行一些优化,例如使用哈希连接,但这会破坏非顶部 (n) 用例。
非顶级 (n) 表现良好。我想知道如何防止优化器在具有 top (n) 子句时选择不同的执行计划,而不会显着改变视图的结构或功能。
例如,如果我在视图中添加一个 select distinct ,优化器总是会选择正确的计划,但视图的功能会发生变化。
sql-server execution-plan sql-server-2016 performance-tuning
我正在尝试创建一个同时在 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) 我有一个分区表...
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
给定 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
我试图了解 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) execution-plan ×10
sql-server ×7
postgresql ×3
index ×2
optimization ×2
query-store ×2
null ×1
order-by ×1
partitioning ×1
plan-cache ×1
ssms ×1