如何从 Azure SQL 数据库中删除错误的执行计划?

Jax*_*ian 13 sql-server execution-plan azure-sql-database

DBCC FREEPROCCACHE在 Azure SQL DB 中不起作用。我还能如何强制计划以一种不会伤害生产系统的方式将自己踢出缓存(即我不能随意更改表)?这是专门为 Entity Framework 创建的 SQL,所以这些不是自我管理的存储过程 - 它是有效的动态 SQL。

(来源是糟糕的索引 -> 糟糕的统计数据等。这一切都已解决,但糟糕的计划不会消失。)

更新: 当他首先到达那里时,我选择了@mrdenny 的解决方案。然而,我成功地使用@Aaron Bertrand 的脚本来执行这项工作。感谢大家的帮助!!

Tod*_*ier 13

Azure SQL 现在直接支持这个

Azure SQL 数据库直接支持清除当前用户数据库的 proc 缓存,无需任何黑客:

ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;
Run Code Online (Sandbox Code Playgroud)

附加信息

以下脚本(由Shannon Gowen编写)可用于逐步观看该过程:

-- run this script against a user database, not master
-- count number of plans currently in cache
select count(*) from sys.dm_exec_cached_plans;

-- Executing this statement will clear the procedure cache in the current database, which means that all queries will have to recompile.
ALTER DATABASE SCOPED CONFIGURATION CLEAR PROCEDURE_CACHE;

-- count number of plans in cache now, after they were cleared from cache
select count(*) from sys.dm_exec_cached_plans;

-- list available plans
select * from sys.dm_exec_cached_plans;
Run Code Online (Sandbox Code Playgroud)


Aar*_*and 12

今天没有明确的方法来做到这一点,但这不是一个永久的场景(仍然不支持 DBCC 命令,但请阅读Query Store)。即使模式更改命中是可以接受的,它也可能不是您想要的,因为它会使与底层对象相关的所有计划无效,而不仅仅是坏的计划。

不是为此寻求功劳,而是构建动态 SQL 以对多个表执行相同的操作非常简单:

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += N'ALTER TABLE '
  + QUOTENAME(SCHEMA_NAME([schema_id])) 
  + '.' + QUOTENAME(name) + ' ADD fake_column INT NULL;
  ALTER TABLE ' 
  + QUOTENAME(SCHEMA_NAME([schema_id]))
  + '.' + QUOTENAME(name) + ' DROP COLUMN fake_column;'
FROM sys.tables
--WHERE name IN, LIKE, etc.

PRINT @sql;

-- if the command > 8K, you can see the second chunk e.g.

PRINT SUBSTRING(@sql, 8001, 8000);

--EXEC sys.sp_executesql @sql;
Run Code Online (Sandbox Code Playgroud)

(我写了一个关于这个“动态 SQL 长度”问题的提示......)

  • 是的,当你“打印”命令时,它只显示 8000 个字节。这是`PRINT` 命令的限制,而不是Azure。如果您运行该命令,即使您无法目视检查整个事情,它也会起作用。 (3认同)

mrd*_*nny 7

向表中添加一个可为空的列,然后删除该列。这将强制 SQL 刷新该对象的缓存。

至于处理所有表格,游标应该可以解决问题。只需使用一个永远不会存在于任何表中的列名,例如 'zzzzzz_go_away' 或其他东西。