我继续在许多论坛和许多博客上看到一个页面的组成如下所示: 页面大小:16 x 512B = 8192B 页眉:= 96B 最大 In_Row 行:= 8060B
这留下 (8192 - 96 - 8060)B = 36B。
好的,这是合乎逻辑且正确的。我的问题是:为什么那么多人说剩下的36B是留给slot array的?
显然,插槽数组在页面上每行给出 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 ;
GO
ALTER DATABASE test
SET ALLOW_SNAPSHOT_ISOLATION ON ;
GO
ALTER DATABASE test …Run Code Online (Sandbox Code Playgroud) sql-server-2008 storage-engine data-pages database-internals
在标准 SQL 中,union all不保证a 的结果按任何顺序排列。所以,像这样:
select 'A' as c union all select 'B'
Run Code Online (Sandbox Code Playgroud)
可以以任何顺序返回两行(尽管实际上在我知道的任何数据库上,'A' 都会出现在 'B' 之前)。
在 SQL Server 中,这变成了使用“串联”物理操作的执行计划。
我可以很容易地想象连接操作会扫描它的输入,返回任何有可用记录的输入。但是,我在网络上发现了以下声明(此处):
Query Processor 将按照操作符出现在计划中的顺序执行这个计划,第一个是最上面的,最后一个是最后一个。
问题:这在实践中是真的吗?这能保证是真的吗?
我还没有在 Microsoft 文档中找到任何参考资料,说明按顺序扫描输入,从第一个到最后一个。另一方面,每当我尝试运行它时,结果表明输入确实是按顺序处理的。
有没有办法让引擎一次处理多个输入?我的测试(使用比常量更复杂的表达式)是在支持并行的 8 核机器上进行的,并且大多数查询确实利用了并行性。
在SQL中,据我所知,逻辑查询处理顺序,也就是概念解释顺序,以FROM开头的方式如下:
按照这个列表很容易看出为什么 WHERE 子句中不能有 SELECT 别名,因为别名还没有被创建。T-SQL (SQL Server) 严格遵循这一点,在通过 SELECT 之前不能使用 SELECT 别名。
但是在 MySQL 中,可以在 HAVING 子句中使用 SELECT 别名,即使它应该(逻辑上)在 SELECT 子句之前处理。这怎么可能?
举个例子:
SELECT YEAR(orderdate), COUNT(*) as Amount
FROM Sales.Orders
GROUP BY YEAR(orderdate)
HAVING Amount>1;
Run Code Online (Sandbox Code Playgroud)
该语句在 T-SQL 中无效(因为 HAVING 指的是 SELECT 别名Amount)...
Msg 207, Level 16, State 1, Line 5
Invalid column name 'Amount'.
Run Code Online (Sandbox Code Playgroud)
...但在 MySQL 中工作得很好。
基于此,我想知道:
在 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
Run Code Online (Sandbox Code Playgroud)
这两者在以下几点上有何不同?
为什么第二次“回滚”是瞬时的?我不完全确定它是否可以称为回滚。我的猜测是,事务日志是随着执行的进行而写入的,一旦它意识到没有足够的空间来完全完成任务,它就会停止并显示一些“结束”消息,而不提交。
当第一次回滚花费这么多时间(回滚单线程)时会发生什么?
2.1. SQL Server 会返回并撤消LDF文件中的条目吗?
2.2. 该LDF文件大小在回滚结束变得更小(从DBCC SQLPERF(LOGSPACE))
另一个问题:在第二种情况下,SQL Server 开始使用LDF文件的速度非常快。就我而言,它在前几分钟(< 4 分钟)内从 18% 的使用率增加到 90% …
sql-server sql-server-2008-r2 database-internals rollback transaction-log
是什么导致将对象名称传递给系统存储过程是合法的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.
sp_helptext [dbo].[myproc] -- Msg 102, Level 15, State 1, Line 1 incorrect syntax
Run Code Online (Sandbox Code Playgroud)
我不需要单引号有效的.过程名称似乎很奇怪,除非它具有分隔模式名称和过程名称。我正在寻找有关如何将其从带引号的名称自动转换为要作为参数值传递的字符串文字的解释。
我没有要解决的具体问题;我只是对没有记录的事情感到好奇。
sql-server stored-procedures syntax parameter database-internals
作为一个简化的例子,假设我有一个这样的表:
seq | value
----+------
102 | 11954
211 | 43292
278 | 19222
499 | 3843
Run Code Online (Sandbox Code Playgroud)
该表可能包含数亿条记录,我需要经常做这样的查询:
SELECT sum(value) WHERE seq > $a and seq < $b
Run Code Online (Sandbox Code Playgroud)
即使seq被索引,典型的数据库实现也会遍历每一行以计算最佳情况下的总和O(n),其中n是范围的大小。
是否有任何数据库可以像O(log(n))每个查询一样有效地执行此操作?
我所遇到的数据结构称为段树所描述这里。有时也称为范围树或区间树,尽管所有这些名称通常被描述为数据结构的略微不同的变体。
但是,我还没有遇到任何实现这种数据结构的数据库。对于内存结构来说,从头开始实现它很容易,但如果它必须持久化或太大而无法放入内存,则变得棘手。如果有一种在现有数据库之上实现这一点的有效模式,那也会有所帮助。
旁注:这不是仅附加表,因此在这种情况下,诸如保留累积总和之类的解决方案将不起作用。
performance database-design database-recommendation database-internals query-performance
我试图更好地了解 SQL Server 的执行引擎在低内存状态下的行为。说到内存授予,我想知道是否有某种方法可以强制GrantedMemory等于RequiredMemory. (我的猜测是有一个未记录的跟踪标志可以做到这一点。有人知道它是什么吗?)
我有两个问题:
1. 为什么在这种情况下会出现更新冲突而不是阻塞:
-- prepare
drop database if exists [TestSI];
go
create database [TestSI];
go
alter database [TestSI] set READ_COMMITTED_SNAPSHOT ON;
alter database [TestSI] set ALLOW_SNAPSHOT_ISOLATION ON;
go
use [TestSI];
go
drop table if exists dbo.call_test;
create table dbo.call_test ( Id bigint CONSTRAINT [PK_Call] PRIMARY KEY CLUSTERED ( [Id] ASC ), additional int, incl int );
create index ix_Call on dbo.call_test ( additional ) include( incl );
insert into dbo.call_test select 1, 2, 3;
go
Run Code Online (Sandbox Code Playgroud)
第一节:
use [TestSI];
go
set …Run Code Online (Sandbox Code Playgroud) sql-server database-internals locking snapshot-isolation sql-server-2016
看看这个查询。它非常简单(有关表和索引定义以及重现脚本,请参见文章末尾):
SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1 AND 1 = (SELECT 1);
Run Code Online (Sandbox Code Playgroud)
注意:“AND 1 = (SELECT 1) 只是为了防止此查询被自动参数化,我觉得这使问题变得混乱 - 尽管有或没有该子句,它实际上获得了相同的计划
这是计划(粘贴计划链接):
由于那里有一个“top 1”,我很惊讶地看到流聚合运算符。对我来说似乎没有必要,因为保证只有一行。
为了测试这个理论,我尝试了这个逻辑上等效的查询:
SELECT MAX(Revision)
FROM dbo.TheOneders
WHERE Id = 1
GROUP BY Id;
Run Code Online (Sandbox Code Playgroud)
这是那个计划(粘贴计划链接):
果然,group by 计划能够在没有流聚合操作符的情况下通过。
请注意,两个查询都从索引的末尾“向后”读取并执行“前 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 …Run Code Online (Sandbox Code Playgroud) sql-server aggregate database-internals group-by sql-server-2017
在阅读了 Josh Darnell 的Unusual THREADPOOL Waits之后,一位 Twitter 用户提到有一个未记录的跟踪标志可以防止修剪空闲工人:
这个想法是,一旦 SQL Server 创建了足够的线程来为峰值工作负载提供服务,它就不应该在 15 分钟左右的不需要的工作线程之后修剪工作线程(将它们释放到操作系统)。
空闲的工作线程将继续使用资源(例如内存),但是THREADPOOL当突然需要更多工作线程时,不会出现等待的爆发。显然,这在使用 Always On 可用性组时会有所帮助。
这个未记录的跟踪标志是什么,它是如何工作的?
sql-server ×7
aggregate ×1
data-pages ×1
group-by ×1
locking ×1
mysql ×1
parameter ×1
performance ×1
rollback ×1
syntax ×1
trace-flags ×1
union ×1
wait-types ×1