AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / user-6141

Josh Darnell's questions

Martin Hope
Josh Darnell
Asked: 2022-03-22 06:41:52 +0800 CST

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

  • 5

我试图了解 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_statsor中来解释的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 decp
GROUP BY decp.cacheobjtype, decp.objtype
ORDER BY decp.cacheobjtype, decp.objtype;

-- total query stats
SELECT COUNT_BIG(*) AS total_query_stats
FROM sys.dm_exec_query_stats;

SSMS 中上述查询结果的屏幕截图,数字如问题中所述


这些查询绝大多数是未参数化的用户查询,而不是系统查询。我通过按 SQL 文本(从 中提取)排序来验证这一点sys.dm_exec_sql_text。一些例子:

  • 5,000 条不同的“INSERT INTO”语句针对具有不同文字值的同一张表
  • 具有不同 WHERE 子句的 15,000 个不同的“SELECT COUNT(*)”查询
  • 针对具有不同文字值的几个表的 15,000 个不同的“更新”语句

这些都是连接到该服务器的应用程序提交的合法查询。

sql-server sql-server-2016
  • 1 个回答
  • 307 Views
Martin Hope
Josh Darnell
Asked: 2019-08-14 08:33:46 +0800 CST

直方图外的基数估计

  • 15

设置

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

  • 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

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

当询问对此的估计计划时,得出的“估计行数”dbo.Posts为 1,934.99:

EXEC #sp_PostsByCommentCount @CommentCount = 51;

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

DBCC SHOW_STATISTICS('dbo.Posts', [_WA_Sys_00000006_0519C6AF]);

SSMS 中统计输出的屏幕截图

其中的亮点是:

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

问题

传递任何高于 50 的值(最多并包括 2,147,483,647)会导致 1,934.99 行估计。 使用什么计算或值来产生这个估计? 顺便说一下,遗留基数估计器产生 1 行的估计值。

我试过的

以下是我的一些理论,我尝试过的事情,或者我在研究这个问题时能够挖掘到的其他信息。

密度向量

我最初认为这将是密度向量,就像我使用OPTION (OPTIMIZE FOR UNKNOWN). 但是这个 stats 对象的密度向量是 3,744,192 * 0.03030303 = 113,460,所以不是这样。

扩展活动

我尝试运行一个收集query_optimizer_estimate_cardinality事件的扩展事件会话(我从 Paul White 的博客文章Cardinality Estimation: Combining Density Statistics中了解到),并得到了这些有趣的花絮:

<CalculatorList>
  <FilterCalculator CalculatorName="CSelCalcColumnInInterval" Selectivity="-1.000" 
                    CalculatorFailed="true" TableName="[p]" ColumnName="CommentCount" />

  <FilterCalculator CalculatorName="CSelCalcAscendingKeyFilter" Selectivity="0.001" 
                    TableName="[p]" ColumnName="CommentCount" UseAverageFrequency="true" 
                    StatId="4" />
</CalculatorList>

所以看起来CSelCalcAscendingKeyFilter计算器被使用了(另一个说它失败了,不管那是什么意思)。此列不是键,也不是唯一的,也不是必须升序的,但无论如何。

对该术语进行一些谷歌搜索使我找到了一些博客文章:

  • Joe Sack - CSelCalcAscendingKeyFilter 计算器,
  • Itzik Ben-Gan - Seek and You Shall Scan 第二部分:升序键

这些帖子表明新的 CE 将这些直方图之外的估计值基于密度向量和统计数据的修改计数器的组合。不幸的是,我已经排除了密度向量(我认为?!),并且修改计数器为零(sys.dm_db_stats_properties无论如何)。

跟踪标志

Forrest建议我打开 TF 2363 以获取有关估计过程的更多信息。我认为该输出中最相关的是:

Plan for computation:

  CSelCalcAscendingKeyFilter(avg. freq., QCOL: [p].CommentCount)

Selectivity: 0.000516798

这是一个突破(谢谢,Forrest!):这个0.000516798数字(似乎在Selectivity="0.001"上面的 XE 属性中被舍入了)乘以表中的行数是我一直在寻找的估计值(1,934.99)。

我可能遗漏了一些明显的东西,但我无法逆向工程如何在CSelCalcAscendingKeyFilter计算器内部产生该选择性值。

sql-server sql-server-2017
  • 1 个回答
  • 515 Views
Martin Hope
Josh Darnell
Asked: 2018-12-19 07:42:29 +0800 CST

为什么这个流聚合是必要的?

  • 13

查看此查询。这非常简单(请参阅文章末尾的表和索引定义以及重现脚本):

SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1 AND 1 = (SELECT 1);

注意:“AND 1 = (SELECT 1) 只是为了防止此查询被自动参数化,我觉得这混淆了这个问题——不管有没有那个子句,它实际上得到了相同的计划

这是计划(粘贴计划链接):

计划流聚合

由于那里有一个“top 1”,我很惊讶地看到了流聚合运算符。这对我来说似乎没有必要,因为保证只有一排。

为了检验这个理论,我尝试了这个逻辑上等效的查询:

SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1
GROUP BY Id;

这是那个计划(粘贴计划链接):

没有流聚合的计划

果然,group by plan不用stream aggregate operator也能过得去。

请注意,这两个查询都从索引的末尾“向后”读取并执行“top 1”以获得最大修订。

我在这里错过了什么? 流聚合是否真的在第一个查询中起作用,或者它是否应该能够被消除(这只是优化器的一个限制,它不是)?

顺便说一下,我意识到这不是一个非常实际的问题(两个查询都报告 0 毫秒的 CPU 和运行时间),我只是对这里展示的内部结构/行为感到好奇。


这是我在运行上面两个查询之前运行的设置代码:

DROP TABLE IF EXISTS dbo.TheOneders;
GO

CREATE TABLE dbo.TheOneders
(
    Id INT NOT NULL,
    Revision SMALLINT NOT NULL,
    Something NVARCHAR(23),

    CONSTRAINT PK_TheOneders PRIMARY KEY NONCLUSTERED (Id, Revision)
);
GO

INSERT INTO dbo.TheOneders
    (Id, Revision, Something)
SELECT DISTINCT TOP 1000 
    1, m.message_id, 'Do...'
FROM sys.messages m
ORDER BY m.message_id
OPTION (MAXDOP 1);

INSERT INTO dbo.TheOneders
    (Id, Revision, Something)
SELECT DISTINCT TOP 100 
    2, m.message_id, 'Do that thing you do...'
FROM sys.messages m
ORDER BY m.message_id
OPTION (MAXDOP 1);
GO
sql-server group-by
  • 1 个回答
  • 841 Views
Martin Hope
Josh Darnell
Asked: 2018-12-05 13:15:03 +0800 CST

过滤列是否应该始终在键/包含中?

  • 10

我正在考虑在我的 Stack Overflow 数据库副本中创建过滤索引。像这样的东西,例如:

CREATE UNIQUE NONCLUSTERED INDEX IX_DisplayName_Filtered
    ON dbo.Users (DisplayName)
    WHERE Reputation > 400000;

我是否应该始终将过滤表达式中的列(Reputation在本例中)添加到键或包含索引,或者将它放在过滤表达式中就足够了吗?

sql-server filtered-index
  • 1 个回答
  • 1236 Views
Martin Hope
Josh Darnell
Asked: 2018-07-17 12:17:47 +0800 CST

所有 XTP_THREAD_POOL 进程都在做什么?

  • 5

我刚刚在sp_who使用MEMORY_OPTIMIZED表的 SQL Server 2016 实例上运行,我看到几个XTP_THREAD_POOL进程正在运行:

xtp 废话

有关输出的其他一些详细信息:

  • 结果集中正好有 6XTP_THREAD_POOL行
  • 我的系统有两个逻辑核心
    • 具体来说,它是一个带有 2 个插槽的虚拟机——每个插槽容纳一个 1 核处理器
  • 所有这些任务都作为后台运行 (sa)

这些进程在做什么?我在 Google 上找不到太多关于此任务名称的信息。

TIA

sql-server sql-server-2016
  • 2 个回答
  • 3581 Views
Martin Hope
Josh Darnell
Asked: 2018-07-13 09:14:27 +0800 CST

这个表情变化过程是什么?

  • 5

考虑这个表定义:

CREATE TABLE [dbo].[Post]
(
    [Id] INT IDENTITY(1,1) NOT NULL,
    [PostType] VARCHAR(10) NOT NULL,

    CONSTRAINT [CK_Post_PostType] CHECK ([PostType] IN ('Question', 'Answer', 'Comment'))
)

如果我运行它然后查看sys.check_constraints:

select [definition] 
from sys.check_constraints
where [name] = 'CK_Post_PostType';

这是输出:

([PostType]='Comment' OR [PostType]='Answer' OR [PostType]='Question')

所以它将我的“in”语句改为一系列“or”语句。

同样的事情是真实的(至少)

  • BETWEEN(更改为OR语句)和
  • CAST(变为CONVERT)。

我意识到这不是 SQL Server 中的功能问题,因为这些表达式在逻辑上是等效的。但这会导致 SSDT 等模式比较工具出现问题,因为源代码与部署的代码不同步。我在这里更详细地介绍了这个问题:SSDT 问题:一遍又一遍地部署相同的更改

这个转换过程/行为有名称吗?是否有关于可能发生的不同转换的任何文档,以便我们可以为它们做好计划(或尽量避免它们)?

sql-server terminology
  • 1 个回答
  • 142 Views
Martin Hope
Josh Darnell
Asked: 2018-04-05 11:49:25 +0800 CST

为什么 CHECKDB 读取具有内存优化表的数据库上的事务日志文件?

  • 16

tl;dr:为什么 CHECKDB 读取具有内存优化表的用户数据库的事务日志?


看起来 CHECKDB 在检查我的一个数据库时正在读取用户数据库的事务日志文件 - 特别是使用内存中 OLTP 表的数据库。

该数据库的 CHECKDB 仍会在合理的时间内完成,所以我主要只是对这种行为感到好奇;但它绝对是该实例上所有数据库中 CHECKDB 持续时间最长的。

在查看 Paul Randal 的史诗“ CHECKDB From Every Angle:所有 CHECKDB 阶段的完整描述”时,我看到 SQL 2005 之前的 CHECKDB用于读取日志以获得数据库的一致视图。但由于这是 2016 年,它使用内部数据库快照。

但是,快照的先决条件之一是:

源数据库不得包含 MEMORY_OPTIMIZED_DATA 文件组

我的用户数据库有这些文件组之一,所以看起来快照不在表中。

根据CHECKDB 文档:

如果无法创建快照,或指定了 TABLOCK,DBCC CHECKDB 将获取锁以获得所需的一致性。在这种情况下,需要独占数据库锁来执行分配检查,并且需要共享表锁来执行表检查。

好的,所以我们正在执行数据库和表锁定而不是快照。但这仍然不能解释为什么它必须读取事务日志。那么给出了什么?

我在下面提供了一个脚本来重现该场景。它用于sys.dm_io_virtual_file_stats标识日志文件读取。

请注意,大多数时候它只读取日志的一小部分 (480 KB),但偶尔会读取更多 (48.2 MB)。在我的生产场景中,当我们运行 CHECKDB 时,它会在每晚午夜读取大部分日志文件(2 GB 文件中的约 1.3 GB)。

这是到目前为止我使用脚本获得的输出示例:

collection_time            num_of_reads     num_of_bytes_read
2018-04-04 15:12:29.203    106              50545664

或这个:

collection_time            num_of_reads     num_of_bytes_read
2018-04-04 15:25:14.227    1                491520

如果我用常规表替换内存优化对象,输出如下所示:

collection_time            num_of_reads     num_of_bytes_read
2018-04-04 15:21:03.207    0                0

为什么 CHECKDB 正在读取日志文件?特别是,为什么它偶尔会读取日志文件的大部分内容?

这是实际的脚本:

-- let's have a fresh DB
USE [master];

IF (DB_ID(N'LogFileRead_Test') IS NOT NULL) 
BEGIN
    ALTER DATABASE [LogFileRead_Test]
    SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
    DROP DATABASE [LogFileRead_Test];
END

GO
CREATE DATABASE [LogFileRead_Test]

GO
ALTER DATABASE [LogFileRead_Test]
MODIFY FILE
(
    NAME = LogFileRead_Test_log,
    SIZE = 128MB
);

-- Hekaton-yeah, I want memory optimized data
GO
ALTER DATABASE [LogFileRead_Test]
ADD FILEGROUP [LatencyTestInMemoryFileGroup] CONTAINS MEMORY_OPTIMIZED_DATA;

GO
ALTER DATABASE [LogFileRead_Test]
ADD FILE 
(
    NAME = [LatencyTestInMemoryFile], 
    FILENAME = 'C:\Program Files\Microsoft SQL Server\MSSQL13.SQL2016\MSSQL\DATA\LogFileRead_Test_SessionStateInMemoryFile'
) TO FILEGROUP [LatencyTestInMemoryFileGroup];

GO
USE [LogFileRead_Test]

GO
CREATE TYPE [dbo].[InMemoryIdTable] AS TABLE (
    [InMemoryId] NVARCHAR (88) COLLATE Latin1_General_100_BIN2 NOT NULL,
    PRIMARY KEY NONCLUSTERED HASH ([InMemoryId]) WITH (BUCKET_COUNT = 240))
    WITH (MEMORY_OPTIMIZED = ON);

GO
CREATE TABLE [dbo].[InMemoryStuff] (
    [InMemoryId]   NVARCHAR (88)    COLLATE Latin1_General_100_BIN2 NOT NULL,
    [Created]     DATETIME2 (7)    NOT NULL,
    CONSTRAINT [PK_InMemoryStuff_InMemoryId] PRIMARY KEY NONCLUSTERED HASH ([InMemoryId]) WITH (BUCKET_COUNT = 240)
)
WITH (MEMORY_OPTIMIZED = ON);

GO
-- RBAR is the new black (we need some logs to read)
declare @j int = 0;
while @j < 100000
begin
    INSERT INTO [dbo].[InMemoryStuff](InMemoryId, Created) VALUES ('Description' + CAST(@j as varchar), GETDATE());
    set @j = @j + 1;
end

-- grab a baseline of virtual file stats to be diff'd later
select f.num_of_reads, f.num_of_bytes_read
into #dm_io_virtual_file_stats
from sys.dm_io_virtual_file_stats(default, default) f
where database_id = db_id('LogFileRead_Test') and file_id = FILE_IDEX('LogFileRead_Test_log');

-- hands off my log file, CHECKDB!
GO
DBCC CHECKDB ([LogFileRead_Test]) WITH NO_INFOMSGS, ALL_ERRORMSGS, DATA_PURITY;

-- grab the latest virtual file stats, and compare with the previous capture
GO
select f.num_of_reads, f.num_of_bytes_read
into #checkdb_stats
from sys.dm_io_virtual_file_stats(default, default) f
where database_id = db_id('LogFileRead_Test') and file_id = FILE_IDEX('LogFileRead_Test_log');

select 
        collection_time = GETDATE() 
        , num_of_reads = - f.num_of_reads + t.num_of_reads
        , num_of_bytes_read = - f.num_of_bytes_read + t.num_of_bytes_read
into #dm_io_virtual_file_stats_diff
from #dm_io_virtual_file_stats f, #checkdb_stats t;

drop table #checkdb_stats;
drop table #dm_io_virtual_file_stats;

-- CHECKDB ignored my comment
select collection_time, num_of_reads, num_of_bytes_read
from #dm_io_virtual_file_stats_diff d
order by d.collection_time;

drop table #dm_io_virtual_file_stats_diff;

-- I was *not* raised in a barn
USE [master];

ALTER DATABASE [LogFileRead_Test]
SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE [LogFileRead_Test];

由于此重现通常只生成 1 或 106 次日志文件读取,我想我会使用 file_read 和 file_read_completed 扩展事件会话深入研究 1。

name                timestamp                   mode        offset  database_id file_id size    duration
file_read           2018-04-06 10:51:11.1098141 Contiguous  72704   9           2       0       NULL    
file_read_completed 2018-04-06 10:51:11.1113345 Contiguous  72704   9           2       491520  1       

这是 VLF 详细信息 ( DBCC LOGINFO()),用于这些偏移量的上下文等:

RecoveryUnitId  FileId  FileSize    StartOffset FSeqNo  Status  Parity  CreateLSN
0               2       2031616     8192        34      2       64      0
0               2       2031616     2039808     35      2       64      0
0               2       2031616     4071424     36      2       64      0
0               2       2285568     6103040     37      2       64      0
0               2       15728640    8388608     38      2       64      34000000005200001
0               2       15728640    24117248    39      2       64      34000000005200001
0               2       15728640    39845888    40      2       64      34000000005200001
0               2       15728640    55574528    0       0       0       34000000005200001
0               2       15728640    71303168    0       0       0       34000000005200001
0               2       15728640    87031808    0       0       0       34000000005200001
0               2       15728640    102760448   0       0       0       34000000005200001
0               2       15728640    118489088   0       0       0       34000000005200001

因此,CHECKDB 操作:

  • 开始将 63 KB(64,512 字节)读入第一个 VLF,
  • 读取 480 KB(491,520 字节),以及
  • 没有读取 VLF的最后 1441 KB(1,475,584 字节)

我还捕获了调用堆栈,以防它们有帮助。

file_read 调用堆栈:

(00007ffd`999a0860)   sqlmin!XeSqlPkg::file_read::Publish+0x1dc   |  (00007ffd`999a0b40)   sqlmin!XeSqlPkg::file_read_enqueued::Publish
(00007ffd`9a825e30)   sqlmin!FireReadEvent+0x118   |  (00007ffd`9a825f60)   sqlmin!FireReadEnqueuedEvent
(00007ffd`9980b500)   sqlmin!FCB::AsyncRead+0x74d   |  (00007ffd`9980b800)   sqlmin!FCB::AsyncReadInternal
(00007ffd`9970e9d0)   sqlmin!SQLServerLogMgr::LogBlockReadAheadAsync+0x6a6   |  (00007ffd`9970ec00)   sqlmin!LBH::Destuff
(00007ffd`9970a6d0)   sqlmin!LogConsumer::GetNextLogBlock+0x1591   |  (00007ffd`9970ab70)   sqlmin!LogPoolPrivateCacheBufferMgr::Lookup
(00007ffd`9a9fcbd0)   sqlmin!SQLServerLogIterForward::GetNext+0x258   |  (00007ffd`9a9fd2d0)   sqlmin!SQLServerLogIterForward::GetNextBlock
(00007ffd`9aa417f0)   sqlmin!SQLServerCOWLogIterForward::GetNext+0x2b   |  (00007ffd`9aa418c0)   sqlmin!SQLServerCOWLogIterForward::StartScan
(00007ffd`9aa64210)   sqlmin!RecoveryMgr::AnalysisPass+0x83b   |  (00007ffd`9aa65100)   sqlmin!RecoveryMgr::AnalyzeLogRecord
(00007ffd`9aa5ed50)   sqlmin!RecoveryMgr::PhysicalRedo+0x233   |  (00007ffd`9aa5f790)   sqlmin!RecoveryMgr::PhysicalCompletion
(00007ffd`9aa7fd90)   sqlmin!RecoveryUnit::PhysicalRecovery+0x358   |  (00007ffd`9aa802c0)   sqlmin!RecoveryUnit::CompletePhysical
(00007ffd`9a538b90)   sqlmin!StartupCoordinator::NotifyPhaseStart+0x3a   |  (00007ffd`9a538bf0)   sqlmin!StartupCoordinator::NotifyPhaseEnd
(00007ffd`9a80c430)   sqlmin!DBTABLE::ReplicaCreateStartup+0x2f4   |  (00007ffd`9a80c820)   sqlmin!DBTABLE::RefreshPostRecovery
(00007ffd`9a7ed0b0)   sqlmin!DBMgr::SyncAndLinkReplicaRecoveryPhase+0x890   |  (00007ffd`9a7edff0)   sqlmin!DBMgr::DetachDB
(00007ffd`9a7f2cd0)   sqlmin!DBMgr::CreatePhasedTransientReplica+0x869   |  (00007ffd`9a7f3630)   sqlmin!DBMgr::StrandTransientReplica
(00007ffd`9a7f2ae0)   sqlmin!DBMgr::CreateTransientReplica+0x118   |  (00007ffd`9a7f2cd0)   sqlmin!DBMgr::CreatePhasedTransientReplica
(00007ffd`99ec6d30)   sqlmin!DBDDLAgent::CreateReplica+0x1b5   |  (00007ffd`99ec6f90)   sqlmin!FSystemDatabase
(00007ffd`9abaaeb0)   sqlmin!UtilDbccCreateReplica+0x82   |  (00007ffd`9abab000)   sqlmin!UtilDbccDestroyReplica
(00007ffd`9ab0d7e0)   sqlmin!UtilDbccCheckDatabase+0x994   |  (00007ffd`9ab0ffd0)   sqlmin!UtilDbccRetainReplica
(00007ffd`9ab0cfc0)   sqlmin!DbccCheckDB+0x22d   |  (00007ffd`9ab0d380)   sqlmin!DbccCheckFilegroup
(00007ffd`777379c0)   sqllang!DbccCommand::Execute+0x193   |  (00007ffd`77737d70)   sqllang!DbccHelp
(00007ffd`777e58d0)   sqllang!CStmtDbcc::XretExecute+0x889   |  (00007ffd`777e6250)   sqllang!UtilDbccSetPermissionFailure
(00007ffd`76b02eb0)   sqllang!CMsqlExecContext::ExecuteStmts<1,1>+0x40d   |  (00007ffd`76b03410)   sqllang!CSQLSource::CleanupCompileXactState
(00007ffd`76b03a60)   sqllang!CMsqlExecContext::FExecute+0xa9e   |  (00007ffd`76b043d0)   sqllang!CCacheObject::Release
(00007ffd`76b03430)   sqllang!CSQLSource::Execute+0x981   |  (00007ffd`76b039b0)   sqllang!CSQLLock::Cleanup

file_read_completed 调用堆栈:

(00007ffd`99995cc0)   sqlmin!XeSqlPkg::file_read_completed::Publish+0x1fc   |  (00007ffd`99995fe0)   sqlmin!XeSqlPkg::file_write_completed::Publish
(00007ffd`9a826630)   sqlmin!FireIoCompletionEventLong+0x227   |  (00007ffd`9a8269c0)   sqlmin!IoRequestDispenser::Dump
(00007ffd`9969bee0)   sqlmin!FCB::IoCompletion+0x8e   |  (00007ffd`9969c180)   sqlmin!IoRequestDispenser::Put
(00007ffd`beaa11e0)   sqldk!IOQueue::CheckForIOCompletion+0x426   |  (00007ffd`beaa1240)   sqldk!SystemThread::GetCurrentId
(00007ffd`beaa15b0)   sqldk!SOS_Scheduler::SwitchContext+0x173   |  (00007ffd`beaa18a0)   sqldk!SOS_Scheduler::Switch
(00007ffd`beaa1d00)   sqldk!SOS_Scheduler::SuspendNonPreemptive+0xd3   |  (00007ffd`beaa1db0)   sqldk!SOS_Scheduler::ResumeNoCuzz
(00007ffd`99641720)   sqlmin!EventInternal<SuspendQueueSLock>::Wait+0x1e7   |  (00007ffd`99641ae0)   sqlmin!SOS_DispatcherPool<DispatcherWorkItem,DispatcherWorkItem,SOS_DispatcherQueue<DispatcherWorkItem,0,DispatcherWorkItem>,DispatcherPoolConfig,void * __ptr64>::GetDispatchers
(00007ffd`9aa437c0)   sqlmin!SQLServerLogMgr::CheckLogBlockReadComplete+0x1e6   |  (00007ffd`9aa44670)   sqlmin!SQLServerLogMgr::ValidateBlock
(00007ffd`9970a6d0)   sqlmin!LogConsumer::GetNextLogBlock+0x1b37   |  (00007ffd`9970ab70)   sqlmin!LogPoolPrivateCacheBufferMgr::Lookup
(00007ffd`9a9fcbd0)   sqlmin!SQLServerLogIterForward::GetNext+0x258   |  (00007ffd`9a9fd2d0)   sqlmin!SQLServerLogIterForward::GetNextBlock
(00007ffd`9aa417f0)   sqlmin!SQLServerCOWLogIterForward::GetNext+0x2b   |  (00007ffd`9aa418c0)   sqlmin!SQLServerCOWLogIterForward::StartScan
(00007ffd`9aa64210)   sqlmin!RecoveryMgr::AnalysisPass+0x83b   |  (00007ffd`9aa65100)   sqlmin!RecoveryMgr::AnalyzeLogRecord
(00007ffd`9aa5ed50)   sqlmin!RecoveryMgr::PhysicalRedo+0x233   |  (00007ffd`9aa5f790)   sqlmin!RecoveryMgr::PhysicalCompletion
(00007ffd`9aa7fd90)   sqlmin!RecoveryUnit::PhysicalRecovery+0x358   |  (00007ffd`9aa802c0)   sqlmin!RecoveryUnit::CompletePhysical
(00007ffd`9a538b90)   sqlmin!StartupCoordinator::NotifyPhaseStart+0x3a   |  (00007ffd`9a538bf0)   sqlmin!StartupCoordinator::NotifyPhaseEnd
(00007ffd`9a80c430)   sqlmin!DBTABLE::ReplicaCreateStartup+0x2f4   |  (00007ffd`9a80c820)   sqlmin!DBTABLE::RefreshPostRecovery
(00007ffd`9a7ed0b0)   sqlmin!DBMgr::SyncAndLinkReplicaRecoveryPhase+0x890   |  (00007ffd`9a7edff0)   sqlmin!DBMgr::DetachDB
(00007ffd`9a7f2cd0)   sqlmin!DBMgr::CreatePhasedTransientReplica+0x869   |  (00007ffd`9a7f3630)   sqlmin!DBMgr::StrandTransientReplica
(00007ffd`9a7f2ae0)   sqlmin!DBMgr::CreateTransientReplica+0x118   |  (00007ffd`9a7f2cd0)   sqlmin!DBMgr::CreatePhasedTransientReplica
(00007ffd`99ec6d30)   sqlmin!DBDDLAgent::CreateReplica+0x1b5   |  (00007ffd`99ec6f90)   sqlmin!FSystemDatabase
(00007ffd`9abaaeb0)   sqlmin!UtilDbccCreateReplica+0x82   |  (00007ffd`9abab000)   sqlmin!UtilDbccDestroyReplica
(00007ffd`9ab0d7e0)   sqlmin!UtilDbccCheckDatabase+0x994   |  (00007ffd`9ab0ffd0)   sqlmin!UtilDbccRetainReplica
(00007ffd`9ab0cfc0)   sqlmin!DbccCheckDB+0x22d   |  (00007ffd`9ab0d380)   sqlmin!DbccCheckFilegroup
(00007ffd`777379c0)   sqllang!DbccCommand::Execute+0x193   |  (00007ffd`77737d70)   sqllang!DbccHelp

这些堆栈跟踪与Max 的回答相关联,表明 CHECKDB 正在使用内部快照,尽管存在 Hekaton 表。

我读过快照执行恢复以撤消未提交的事务:

未提交的事务在新创建的数据库快照中回滚,因为数据库引擎在创建快照后运行恢复(数据库中的事务不受影响)。

但这仍然不能解释为什么在我的生产场景中经常读取大量日志文件(偶尔在此处提供的重现中)。我不认为我的应用程序在给定时间有那么多飞行中的交易,而且这里的 repro 中肯定没有任何交易。

sql-server sql-server-2016
  • 1 个回答
  • 977 Views
Martin Hope
Josh Darnell
Asked: 2012-03-31 09:05:48 +0800 CST

这个“映射”表是否需要单独的 Id 列?

  • 12

我有一个表Producers和一个表Products,它们的形式都是:

  • Id- int,主键
  • Name- nvarchar

一个生产者可以携带多个产品,所以我要创建一个名为的表ProducerDetails,它有:

  • ProducerId- int,外键Producers.Id
  • ProductId- int,外键Products.Id

然后我开始质疑自己,所以我想我会问专家。在我的表中添加一个额外的Id(int, Primary key) 列会更好的数据库设计吗?ProducerDetails或者那是不必要的?

如果这有什么不同的话,我正在使用 SQL-Server 2008 R2。

编辑- 我相信这些表之间的关系是多对多的,抱歉我没有说清楚。一个生产者可以携带多种类型的产品,同一产品可以由多个不同的生产者生产。

如果这个问题过于简单,我深表歉意,参照完整性/数据库设计不是我的强项(尽管我正在努力改进)。

sql-server database-design
  • 2 个回答
  • 8131 Views

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve