标签: statistics

如何防止在列上创建统计信息?

我有一个表,其中有一列我不希望在其上创建或更新统计信息。如果我强制查询优化器使用主键上的统计密度而不是该列上的统计直方图,我会得到更好的连接基数估计。自动更新和自动创建统计信息在数据库级别启用,我无法更改。

如果您想建议防止创建统计信息的替代方法,请记住该表用于被数千个不同查询引用的视图中。我无法控制运行的查询。

我最初的策略是使用NOCOMPUTESAMPLE 0 ROWS选项在列上创建统计信息。我的印象是 SQL Server 不会在已经有统计对象的列上自动创建统计信息,但这已经发生在我们的开发和 QA 服务器上。

创建了新的统计信息COL_GROUP。我的NORECOMPUTE统计数据没有更新。我不知道为什么要创建统计信息,而且我自己也无法通过运行查询来触发它。

有没有办法阻止 SQL Server 自动为一列创建统计信息?我的表只有两列,因此防止在单个表上创建自动统计的解决方案也可以解决我的问题。

跟踪标志 4139 和 2371 处于打开状态,以防有所不同。

如果你想玩转表结构,我已经包含了它和下面的示例数据:

CREATE TABLE X_NO_COLUMN_STATS(
    [COL_USER] [varchar](256) NOT NULL,
    [COL_GROUP] [int] NOT NULL,
 CONSTRAINT [PK_X_NO_COLUMN_STATS] PRIMARY KEY CLUSTERED 
(
    [COL_USER] ASC,
    [COL_GROUP] ASC
)WITH (DATA_COMPRESSION = PAGE)
);

-- prevent stats from being updated on COL_GROUP
CREATE STATISTICS [X_NO_COLUMN_STATS__COL_GROUP] ON X_NO_COLUMN_STATS ([COL_GROUP]) WITH NORECOMPUTE, SAMPLE 0 ROWS;

BEGIN TRANSACTION;
INSERT INTO X_NO_COLUMN_STATS VALUES …
Run Code Online (Sandbox Code Playgroud)

sql-server statistics

20
推荐指数
2
解决办法
1080
查看次数

是否有理由手动更新统计信息?

在 SQL Server 中,统计信息会在Auto Update Statistics进入时自动更新True(这是默认设置)。是否有理由在什么情况下手动更新统计信息?

index sql-server maintenance statistics

19
推荐指数
3
解决办法
3874
查看次数

什么是数据库统计信息,我如何从中受益?

我听说过 SQL Server 默认保留的统计信息。他们在跟踪什么,我如何使用这些信息来改进我的数据库?

sql-server-2005 statistics

18
推荐指数
2
解决办法
4万
查看次数

SQL Server 2016 Bad Query Plan 每周锁定一次数据库

每周一次,在过去 5 周内,大约在一天中的同一时间(清晨,可能基于人们开始使用它时的用户活动),SQL Server 2016(AWS RDS,镜像)开始超时很多查询。

所有表上的 UPDATE STATISTICS 总是立即修复它。

在第一次之后,我让它每晚(而不是每周)更新所有表上的所有统计信息,但它仍然发生了,(更新统计信息运行后大约 8 小时,但不是每天运行)。

这最后一次,我启用了查询存储,看看我是否能找到它是哪个特定的查询/查询计划。我想我可以将其缩小为一个:

错误的查询计划

找到该查询后,我添加了一个推荐索引,该索引在这个不常用的查询中缺失(但它确实触及了很多常用表)。

错误的查询计划正在执行索引扫描(在只有 10k 行的表上)。其他以毫秒为单位返回的查询计划,虽然用于执行相同的扫描。最新的查询计划,在创建新索引后只查找。但即使没有该索引,99% 的情况下,它也会在几毫秒内返回,但是,每周需要超过 40 秒。

这是从 2012 年迁移到 SQL Server 2016 后开始发生的。

DBCC CHECKDB 没有返回错误。

  1. 新索引是否会解决问题,使其不再选择糟糕的计划?
  2. 我应该“强制”现在运行良好的计划吗?
  3. 我如何确保这不会发生在另一个查询/计划中?
  4. 这是更大问题的征兆吗?

我刚刚添加的索引:

CREATE NONCLUSTERED INDEX idx_AppointmetnAttendee_AttendeeType
ON [dbo].[AppointmentAttendee] ([UserID],[AttendeeType])

CREATE NONCLUSTERED INDEX [idx_appointment_start] ON [dbo].[Appointment]
(
    [ProjectID] ASC,
    [Start] ASC
)
INCLUDE (   [ID],
    [AllDay],
    [End],
    [Location],
    [Notes],
    [Title],
    [CreatedByID]) WITH (PAD_INDEX = OFF, …
Run Code Online (Sandbox Code Playgroud)

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

17
推荐指数
1
解决办法
8672
查看次数

SQL Server 如何知道谓词是相关的?

在诊断基数估计不佳的 SQL Server 2008 R2 查询(尽管有简单的索引、最新的统计数据等)和查询计划不佳时,我发现了一篇可能相关的知识库文章: FIX:运行查询时性能不佳包含 SQL Server 2008 或 SQL Server 2008 R2 或 SQL Server 2012 中的关联 AND 谓词

我可以猜测知识库文章中“相关”的含义,例如谓词#2 和谓词#1 主要针对相同的行。

但我不知道 SQL Server 是如何知道这些相关性的。表是否需要包含来自两个谓词的列的多列索引?SQL 是否使用统计信息来检查一列中的值是否与另一列相关?还是使用了其他方法?

我问这个有两个原因:

  1. 确定使用此修补程序可以改进我的哪些表和查询
  2. 知道我应该在索引、统计等方面做些什么来影响 #1

performance sql-server statistics sql-server-2008-r2 query-performance

15
推荐指数
1
解决办法
1611
查看次数

stats_column_id 和 index_column_id 不会随着聚集索引的物理顺序改变而更新

除非我误解了列的用途,否则以下代码表明聚集索引结构的更改不会更改sys.stats_columns DMV 中stats_column_id列的序数位置 ( ) 。(在 AdventureWorks2014、AdventureWorks2008R2 中测试)

select i.name, c.name, ic.column_id, ic.index_column_id
from sys.indexes i 
join sys.index_columns ic
    on i.object_id = ic.object_id
    and i.index_id = ic.index_id
join sys.columns c 
    on i.object_id = c.object_id
    and ic.column_id = c.column_id
where i.name = 'PK_BusinessEntityAddress_BusinessEntityID_AddressID_AddressTypeID'
order by ic.key_ordinal;

select sh.name,s.name, c.name, c.column_id, sc.column_id, sc.stats_column_id
from sys.stats s 
join sys.stats_columns sc
    on s.object_id = sc.object_id
    and s.stats_id = sc.stats_id
join sys.columns c 
    on s.object_id = c.object_id
    and sc.column_id = c.column_id
join …
Run Code Online (Sandbox Code Playgroud)

sql-server statistics dmv

15
推荐指数
1
解决办法
678
查看次数

直方图外的基数估计

设置

我在理解基数估计时遇到了一些麻烦。这是我的测试设置:

  • Stack Overflow 数据库 2010 版
  • SQL Server 2017 CU15+GDR (KB4505225) - 14.0.3192.2
  • 新 CE(兼容级别 140)

我有这个过程:

USE StackOverflow2010;
GO

CREATE OR ALTER PROCEDURE #sp_PostsByCommentCount
    @CommentCount int
AS
BEGIN
    SELECT * 
    FROM dbo.Posts p
    WHERE 
        p.CommentCount = @CommentCount
    OPTION (RECOMPILE); 
END;
GO
Run Code Online (Sandbox Code Playgroud)

dbo.Posts表上没有非聚集索引或统计信息(在 上有聚集索引Id)。

当为此要求估计计划时,“估计行数”dbo.Posts是 1,934.99:

EXEC #sp_PostsByCommentCount @CommentCount = 51;
Run Code Online (Sandbox Code Playgroud)

当我询问估计计划时,自动创建了以下统计对象:

DBCC SHOW_STATISTICS('dbo.Posts', [_WA_Sys_00000006_0519C6AF]);
Run Code Online (Sandbox Code Playgroud)

SSMS 中统计输出的屏幕截图

其中的亮点是:

  • 统计数据的采样率非常低,为 1.81% (67,796 / 3,744,192)
  • 仅使用了 31 个直方图步骤
  • “所有密度”值为0.03030303(采样了 33 个不同的值)
  • RANGE_HI_KEY直方图中的最后一个是 50,其中EQ_ROWS1 …

sql-server statistics database-internals cardinality-estimates sql-server-2017

15
推荐指数
1
解决办法
471
查看次数

并行统计更新

在 SQL Server 2008 或更高版本中,是UPDATE STATISTICS WITH FULLSCAN单线程操作还是可以使用并行性?如何使用默认采样更新统计信息 - 它可以使用并行性吗?我没有看到指定MAXDOP更新统计信息的选项。

sql-server-2008 sql-server parallelism statistics

14
推荐指数
1
解决办法
5327
查看次数

SQL Server 索引与统计

之间有什么区别CREATE INDEXCREATE STATISTICS何时该使用的呢?

index sql-server statistics

14
推荐指数
1
解决办法
1万
查看次数

SQL Server 每天重新创建计划

我们的生产环境有这个问题。

Microsoft SQL Server 2008 R2 (SP1) - 10.50.2500.0 (X64) - Windows NT 6.1(内部版本 7601:Service Pack 1)上的企业版(64 位)。

SQL Server 正在删除所有(几乎 100%)旧的执行计划,并在每天夜间(从晚上 11:00 到早上 8:00)重新创建它们。当“自动更新统计信息”处于禁用状态时,甚至会发生这种情况。在过去的 2-3 周内,我们已经开启了“自动更新统计信息”。但它仍在发生。

我们真的不知道是什么触发了这种重新生成计划,但我们确信我们不会手动进行。

唯一真正与计划重新生成时间一致的是我们的数据库维护工作:每日索引重组(碎片为 5-30% 时),以及每日索引重建(碎片超过 30% 时) ) 工作。通常这个日常维护工作只做重组(因为每天的索引碎片永远不会超过 30%)。

影响:

这些新创建的计划使一些 UDF 调用/查询调用(从 UI/网页调用)花费更长的时间(分钟而不是不到 1 秒),因此会话只会堆积起来,使 CPU 接近 90% .

当那些卡住的会话被强行删除(在 DB 端)时,问题就会消失,并且 1)当所有相应的执行计划被手动清除(对于查询)或 2)当 UDF 被更改(对于函数)时。从那一刻起,SQL 服务器创建的任何新计划都会在一天中完美运行,直到第二天早上最终出现相同的问题。此外,这种行为并不是 100% 一致的,我们并不是每天早上都能看到它。但是有一段时间我们已经连续 4-5 天看到它了。

问题发生在工作日的早晨,这似乎是更频繁地访问 UI/网页的时候。

有没有人知道是什么导致了这个问题以及如何解决这个问题?任何帮助将非常感激。

sql-server-2008 sql-server statistics execution-plan

14
推荐指数
1
解决办法
382
查看次数