Questions tagged «database-internals»

有关数据库引擎内部工作的技术问题。

2
为什么临时表比急切的线轴更有效地解决万圣节问题?
考虑以下查询,该查询仅在源表中的行尚未插入目标表中时才插入它们: INSERT INTO dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR WITH (TABLOCK) SELECT maybe_new_rows.ID FROM dbo.A_HEAP_OF_MOSTLY_NEW_ROWS maybe_new_rows WHERE NOT EXISTS ( SELECT 1 FROM dbo.HALLOWEEN_IS_COMING_EARLY_THIS_YEAR halloween WHERE maybe_new_rows.ID = halloween.ID ) OPTION (MAXDOP 1, QUERYTRACEON 7470); 一种可能的计划形状包括合并联接和渴望的线轴。热心的线轴操作员出席以解决万圣节问题: 在我的计算机上,以上代码在大约6900毫秒内执行。问题的底部包括创建表的Repro代码。如果我对性能不满意,则可以尝试加载要插入到临时表中的行,而不是依赖急切的假脱机。这是一种可能的实现: DROP TABLE IF EXISTS #CONSULTANT_RECOMMENDED_TEMP_TABLE; CREATE TABLE #CONSULTANT_RECOMMENDED_TEMP_TABLE ( ID BIGINT, PRIMARY KEY (ID) ); INSERT INTO #CONSULTANT_RECOMMENDED_TEMP_TABLE …

4
索引唯一性开销
我一直在与我的办公室中的各种开发人员就索引的成本以及唯一性是有利还是昂贵(可能两者都有)进行辩论。问题的症结在于我们的竞争资源。 背景 之前,我曾读过一篇讨论,其中指出Unique索引并不需要额外维护,因为Insert操作会隐式地检查索引是否适合B树,并且如果在非唯一索引中找到重复项,则会在其后附加一个唯一化符。键的结尾,否则直接插入。在此事件序列中,Unique索引没有附加成本。 我的同事通过说这Unique是在寻求B树中的新职位之后强制执行的第二项操作来抗衡此声明,因此,与非唯一索引相比,维护成本更高。 最糟糕的是,我看到了带有标识列(本质上是唯一的)的表,该列是表的集群键,但明确地表示为非唯一。最糟糕的是我对唯一性的痴迷,并且所有索引都被创建为唯一,并且当不可能定义与索引的显式唯一关系时,我将表的PK附加到索引的末尾以确保唯一性得到保证。 我经常参与开发团队的代码审查,并且我需要能够提供一些一般性的指导方针,以使他们可以遵循。是的,应该评估每个索引,但是当您有五台服务器,每台服务器都有数千个表,并且一个表上有多达二十个索引时,您需要能够应用一些简单的规则来确保一定水平的质量。 题 Insert与维护非唯一索引的成本相比,唯一性是否会在后端增加成本?其次,将表的主键附加到索引的末尾以确保唯一性有什么问题? 表定义示例 create table #test_index ( id int not null identity(1, 1), dt datetime not null default(current_timestamp), val varchar(100) not null, is_deleted bit not null default(0), primary key nonclustered(id desc), unique clustered(dt desc, id desc) ); create index [nonunique_nonclustered_example] on #test_index (is_deleted) include …

2
搜索FILESTREAM内部信息
在Microsoft SQL Server 2012上激活FILESTREAM功能后,SQL Server将在系统上创建“隐藏”共享。份额定义如下: Sharename FILESTREAM_SHARE Path \\?\GLOBALROOT\Device\RsFx0320\<localmachine>\FILESTREAM_SHARE Remark SQL Server FILESTREAM share Maximum users unlimited Users Caching Manual caching of documents Permissions NT-AUTHORITY\Authenticated Users, FULL 该名称是您最初在SQL Server配置管理器中配置FILESTREAM时提供的共享的名称。但是,这是为了什么呢? 至今 我从以下位置开始阅读了所有可用的FILESTREAM文档: 文件流(SQL Server) 启用和配置FILESTREAM 创建一个启用了FILESTREAM的数据库 创建用于存储FILESTREAM数据的表 ...以及所有相关的 FILESTREAM与其他SQL Server功能的兼容性 FILESTREAM DDL,函数,存储过程和视图 使用OpenSqlFilestream访问FILESTREAM数据 论文SQL Server 2008-SQL Server 2008中的文件流存储 以及FILESTREAM(OLTP)---设计关键任务OLTP解决方案的技术参考指南,其中引用了许多其他材料 ...但是没有提及份额,份额或用途。您输入名称,SQL Server将在后台创建共享。 …

2
为什么MySQL允许HAVING使用SELECT别名?
据我所知,在SQL中,逻辑查询处理顺序(即概念解释顺序)以以下方式从FROM开始: 从 哪里 通过...分组 拥有 选择 订购 在此列表之后,很容易看出为什么在WHERE子句中没有SELECT别名,因为尚未创建别名。T-SQL(SQL Server)严格遵循此原则,在传递SELECT之前,您不能使用SELECT别名。 但是在MySQL中,即使应该(在逻辑上)在SELECT子句之前对其进行处理,也可以在HAVING子句中使用SELECT别名。这怎么可能? 举个例子: SELECT YEAR(orderdate), COUNT(*) as Amount FROM Sales.Orders GROUP BY YEAR(orderdate) HAVING Amount>1; 该语句在T-SQL中无效(因为HAVING引用了SELECT别名Amount)... Msg 207, Level 16, State 1, Line 5 Invalid column name 'Amount'. ...但是在MySQL中工作正常。 基于此,我想知道: MySQL是否在SQL规则中采取捷径来帮助用户?也许使用某种预分析? 还是MySQL使用的概念解释顺序与我遵循的所有RDBMS遵循的顺序不同?

1
在运行查询时如何模拟低内存状态
我试图更好地了解SQL Server的执行引擎在低内存状态下的行为。说到内存授予,我想知道是否有某种方法可以强制GrantedMemory等于RequiredMemory。(我的猜测是有一个未记录的跟踪标志可以做到这一点。有人知道它是什么吗?)

1
是什么允许SQL Server用对象名称交换传递给系统过程的字符串
是什么导致将对象名称传递给系统存储过程合法sp_helptext呢? 什么机制将对象名称转换为字符串? 例如 -- works sp_helptext myproc sp_helptext [myproc] sp_helptext [dbo.myproc] -- and behaves the same as a string sp_helptext 'myproc' sp_helptext 'dbo.myproc' -- does not work sp_helptext dbo.myproc -- Msg 102, Level 15, State 1, Line 1 incorrect syntax near '.' -- an additional case that does not work. …

2
这两个SQL Server回滚有何不同?
在SQL Server 2008 R2中,这两个回滚有何不同: 运行ALTER语句几分钟,然后单击“取消执行”。完全回滚需要几分钟。 运行相同的ALTER语句,但是请确保该LDF文件的大小不足以使其成功完成。一旦达到LDF限制并且不允许“自动增长”,查询执行将立即停止(或发生回滚),并显示以下错误消息: The statement has been terminated. Msg 9002, Level 17, State 4, Line 1 The transaction log for database 'SampleDB' is full. To find out why space in the log cannot be reused, see the log_reuse_wait_desc column in sys.databases 这两个方面在以下几点上有何不同? 为什么第二个“回滚”是瞬时的?我不确定是否可以将其称为回滚。我的猜测是,事务日志是在执行过程中编写的,一旦它意识到没有足够的空间来完全完成任务,它就会以一些“结束”消息停止,而不会提交。 第一次回滚需要很多时间(回滚是单线程的)会发生什么? 2.1。SQL Server会返回并撤消LDF文件中的输入吗? 2.2。该LDF文件大小在回滚结束变得更小(从DBCC …

1
插槽阵列和总页面大小
我继续在许多论坛和博客中读到一个页面构成,如下所示:页面大小:16 x 512B = 8192B页面标题:= 96B最大行内行:= 8060B 这留下(8192-96-8060)B = 36B。 好的,这是合乎逻辑且正确的。我的问题是:为什么有那么多人说剩下的36B是为插槽阵列保留的? 显然,插槽数组在页面上每行提供2B的空间;因此,它可以小至2B,大至1472B: 2B:1行* 2B = 2B 1472B:8096B = n * 9B(带有开销的最小行大小...考虑单个TINYINT列)+ n * 2B(每行的插槽阵列成本)=> 8096 = 11n => n = 8096/11 = 736。 736 * 2B = 1472B。 由于使用14B版本标记,因此我的排名为20。 USE master ; GO CREATE DATABASE test ; GO USE test …

1
为什么这些类似的查询使用不同的优化阶段(事务处理与快速计划)?
此连接项中的示例代码 显示一个错误 SELECT COUNT(*) FROM dbo.my_splitter_1('2') L1 INNER JOIN dbo.my_splitter_1('') L2 ON L1.csv_item = L2.csv_item 返回正确的结果。但是以下内容返回的结果不正确(2014年使用新的Cardinality Estimator) SELECT (SELECT COUNT(*) FROM dbo.my_splitter_1('2') L1 INNER JOIN dbo.my_splitter_1('') L2 ON L1.csv_item = L2.csv_item) 因为它错误地将L2的结果加载到公共子表达式假脱机中,然后重播L1结果的结果。 我对为什么两个查询之间的行为差​​异感到好奇。跟踪标志8675显示工作的一个进入search(0) - transaction processing而失败的一个进入search(1) - quick plan。 因此,我认为其他转换规则的可用性是行为差异的背后原因(例如,禁用BuildGbApply或GenGbApplySimple似乎可以解决此问题)。 但是,为什么针对这些非常相似的查询的两个计划会遇到不同的优化阶段?根据我的阅读search (0),至少需要三个表,并且在第一个示例中肯定不满足该条件。

1
为什么需要汇总此流?
查看此查询。这非常简单(有关表和索引的定义以及repro脚本,请参见文章结尾): 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; 这是该计划(粘贴计划链接): 果然,按计划分组无需流聚合运算符就可以通过。 请注意,两个查询均从索引末尾读取“向后”,并执行“ top 1”以获取最大修订。 我在这里想念什么? 流聚合实际上是在第一个查询中进行工作,还是应该将其消除(这不是优化器的限制,而并非如此)? 顺便说一句,我意识到这不是一个非常实际的问题(两个查询都报告了0 ms的CPU和经过的时间),我只是好奇这里展示的内部/行为。 这是我在运行上述两个查询之前运行的设置代码: DROP TABLE IF EXISTS dbo.TheOneders; …

1
SQL Server在哪里将表的IDENTITY VALUE物理存储在哪里?
我希望有人可以指出我在这个方向上的正确方向。到目前为止,这是我的工作。 SELECT * FROM sys.identity_columns是一个提供“ last_value”的系统视图,但是该视图的定义使用了内部函数IdentityProperty(colName, 'LastValue')-因此是死胡同(不是从系统表中拉出它)。 互联网上的任何地方(我看过的地方)都建议使用DBCC IDENT_...命令来发现该值,但这仍然使我不清楚其实际存储位置。 因此,我开始DBCC PAGE(TestDB,1,1325,3)针对测试工具数据库搜索单个页面,并使用RESEED命令在值10和12之间重新设定种子。 在执行此操作时,我注意到上的十六进制值IAM: Header,IAM: Single Page Allocations并且IAM: Extent Alloc Status Slot 1所有值都已更改。(并且意识到它们无论如何都会随着bUse1值的变化而定期变化,而bUse1值本身也会逐渐变化)。 所以另一个死胡同,我全都没主意了。我还能在哪里搜索? 我正在运行SQL Server2014。我对内部知识有无限的渴望,并且还没有遇到像这样难以捉摸的东西。它引起了我的注意,因为从理论上讲,它(一个绝对值)存储在某个位置,并且应该(可以说)是可定位的。在我探索内部存储的数据/元数据的位置时,这个特殊的值使我感到难以捉摸。我猜测/希望有人会来告诉我,您可以接受,DBCC PAGE但我找错了地方。

3
级联物理操作:是否保证执行顺序?
在标准SQL中,union all不能保证a的结果以任何顺序排列。因此,类似: select 'A' as c union all select 'B' 可以按任何顺序返回两行(尽管实际上,在我所知道的任何数据库上,“ A”都将排在“ B”之后)。 在SQL Server中,这变成使用“串联”物理操作的执行计划。 我很容易想到,连接操作将扫描其输入,并返回具有可用记录的任何输入。但是,我在网上(此处)找到了以下声明: 查询处理器将按照操作员出现在计划中的顺序执行该计划,第一个是最上一个,最后一个是最后一个。 问题:实际上是这样吗?这保证是真的吗? 我没有在Microsoft文档中找到任何参考,从头到尾按顺序扫描输入。另一方面,每当我尝试运行它时,结果表明实际上确实按顺序处理了输入。 有没有一种方法可以让引擎一次处理多个输入?我的测试(使用比常量更复杂的表达式)是在启用了并行的8核计算机上进行的,大多数查询的确利用了并行性。

1
列出特定表的ROW_OVERFLOW_DATA页
我正在尝试获取具有ROW_OVERFLOW_DATA行的表的页面列表。我可以从未记录的DMV中获得分配页面的列表sys.db_db_database_page_allocations,但是,该DMV的输出中似乎没有列出ROW_OVERFLOW_DATA页面。还有我无法找到的其他DMV吗? 最小,完整和(希望!)可验证的示例: USE tempdb; IF OBJECT_ID(N'dbo.t', N'U') IS NOT NULL DROP TABLE dbo.t; GO CREATE TABLE dbo.t ( rownum int NOT NULL IDENTITY(1,1) PRIMARY KEY CLUSTERED , on_row_data varchar(30) NOT NULL DEFAULT ('on_row_data') , off_row_data varchar(MAX) NOT NULL DEFAULT REPLICATE('A', 20000) --PLENTY BIG ENOUGH! ) WITH (DATA_COMPRESSION = NONE); --not …

2
用于有效范围聚合查询的数据库?
作为一个简化的示例,假设我有一个像这样的表: seq | value ----+------ 102 | 11954 211 | 43292 278 | 19222 499 | 3843 该表可能包含数亿条记录,我需要经常执行以下查询: SELECT sum(value) WHERE seq > $a and seq < $b 即使seq已建立索引,典型的数据库实现也将遍历每一行以计算最佳情况下的总和O(n),其中n范围的大小是。 是否有任何数据库可以像在O(log(n))每个查询中一样有效地做到这一点? 我所遇到的数据结构称为段树所描述这里。尽管所有这些名称通常都被描述为数据结构略有不同的变体,但有时也称为范围树或间隔树。 但是,我还没有遇到任何实现这种数据结构的数据库。对于内存结构,从头开始实现它很容易,但是如果必须持久或太大而无法容纳到内存中,则变得棘手。如果有一个有效的模式可以在现有数据库之上实施,那也可能会有所帮助。 旁注:这不是仅追加表,因此在这种情况下,诸如保留累计和之类的解决方案将不起作用。

2
为什么嵌套循环联接仅支持左联接?
在Craig Freedman的博客Nested Loops Join中,他解释了为什么嵌套循环联接不能支持正确的外部联接: 问题在于,我们多次扫描内部表–对外部联接的每一行扫描一次。在这些多次扫描中,我们可能多次遇到相同的内部行。在什么时候我们可以得出结论,特定的内部行尚未或将不会加入? 有人可以用一种非常简单且具有教育意义的方式来解释这一点吗? 这是否意味着循环从外部表(R1)开始并扫描内部表(R2)? 我了解,对于R1不与相连的值,R2应将其替换为,NULL这样结果集将变为(NULL, R2)。对我来说,似乎无法返回不加入R2时返回值R1,因为它不知道R2要返回哪个值。但这不是它的解释方式。还是? SQL Server会在事实上优化(经常替换)RIGHT JOIN用LEFT JOIN,但问题是解释为什么它在技术上是不可能的NESTED LOOPS JOIN使用/支持RIGHT JOIN逻辑。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.