当我注意到我的一些插入花费的时间比预期的要长时,我正在做一个涉及 CCI 的演示。要重现的表定义:
DROP TABLE IF EXISTS dbo.STG_1048576;
CREATE TABLE dbo.STG_1048576 (ID BIGINT NOT NULL);
INSERT INTO dbo.STG_1048576
SELECT TOP (1048576) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) RN
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;
DROP TABLE IF EXISTS dbo.CCI_BIGINT;
CREATE TABLE dbo.CCI_BIGINT (ID BIGINT NOT NULL, INDEX CCI CLUSTERED COLUMNSTORE);
Run Code Online (Sandbox Code Playgroud)
对于测试,我将从临时表中插入所有 1048576 行。只要它没有因某种原因被修剪,这就足以填充一个压缩的行组。
如果我插入所有整数 mod 17000,它需要不到一秒钟的时间:
TRUNCATE TABLE dbo.CCI_BIGINT;
INSERT INTO dbo.CCI_BIGINT WITH (TABLOCK)
SELECT ID % 17000
FROM dbo.STG_1048576
OPTION (MAXDOP 1);
Run Code Online (Sandbox Code Playgroud)
SQL Server 执行时间:CPU 时间 = 359 …
在我目前的环境中,我正在与 NOLOCK 作斗争。我听到的一个论点是锁定的开销会减慢查询速度。所以,我设计了一个测试来看看这个开销可能有多少。
我发现 NOLOCK 实际上减慢了我的扫描速度。
起初我很高兴,但现在我很困惑。我的测试以某种方式无效吗?NOLOCK 实际上不应该允许稍微快一点的扫描吗?这里发生了什么事?
这是我的脚本:
USE TestDB
GO
--Create a five-million row table
DROP TABLE IF EXISTS dbo.JustAnotherTable
GO
CREATE TABLE dbo.JustAnotherTable (
ID INT IDENTITY PRIMARY KEY,
notID CHAR(5) NOT NULL )
INSERT dbo.JustAnotherTable
SELECT TOP 5000000 'datas'
FROM sys.all_objects a1
CROSS JOIN sys.all_objects a2
CROSS JOIN sys.all_objects a3
/********************************************/
-----Testing. Run each multiple times--------
/********************************************/
--How fast is a plain select? (I get about 587ms)
DECLARE @trash CHAR(5), @dt DATETIME = SYSDATETIME()
SELECT @trash …
Run Code Online (Sandbox Code Playgroud) 在 SQL Server 中,Except运算符如何在幕后工作的内部算法是什么?它是否在内部获取每一行的哈希值并进行比较?
David Lozinksi 进行了一项研究,SQL:在不存在新记录的地方插入新记录的最快方法他表明,对于大量行,Except 语句是最快的;与我们下面的结果密切相关。
假设:我认为 Left join 会最快,因为它只比较 1 列,Except 花费的时间最长,因为它必须比较所有列。
有了这些结果,现在我们的想法是,Except 自动并在内部获取每一行的哈希值?我查看了除非执行计划,它确实使用了一些哈希。
背景:我们的团队正在比较两个堆表。表 A 不在表 B 中的行被插入到表 B 中。
堆表(来自旧文本文件系统)没有主键/guids/标识符。有些表有重复的行,所以我们找到每一行的Hash,并去除重复,并创建主键标识符。
1)首先我们运行一个except语句,排除(哈希列)
select * from TableA
Except
Select * from TableB,
Run Code Online (Sandbox Code Playgroud)
2)然后我们在HashRowId上的两个表之间运行左连接比较
select *
FROM dbo.TableA A
left join dbo.TableB B
on A.RowHash = B.RowHash
where B.Hash is null
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,Except Statement Insert 是最快的。
结果实际上与 David Lozinksi 的测试结果接近
performance sql-server hashing sql-server-2016 except performance-tuning
我有下表,其中有 750 万条记录:
CREATE TABLE [dbo].[TestTable](
[Id] [int] IDENTITY(1,1) NOT NULL,
[TestCol] [nvarchar](50) NOT NULL,
[TestCol2] [nvarchar](50) NOT NULL,
[TestCol3] [nvarchar](50) NOT NULL,
[Anonymised] [tinyint] NOT NULL,
[Date] [datetime] NOT NULL,
CONSTRAINT [PK_TestTable] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)
我注意到当日期字段上有非聚集索引时:
CREATE NONCLUSTERED INDEX IX_TestTable_Date ON [dbo].[TestTable] ([Date])
Run Code Online (Sandbox Code Playgroud)
- 我运行以下查询:
UPDATE TestTable
SET TestCol='*GDPR*', TestCol2='*GDPR*', TestCol3='*GDPR*', Anonymised=1
WHERE [Date] <= …
Run Code Online (Sandbox Code Playgroud) 我有一个非常大的查询,它的运行速度比我想象的要慢,但是对查询执行计划的深入研究并没有帮助揭示这种缓慢。最终我缩小了范围:try_parse
是罪魁祸首!
正常查询:
SELECT CloseDate
FROM MyTable
(4959 row(s) affected)
SQL Server Execution Times:
CPU time = 0 ms, elapsed time = 17 ms.
Run Code Online (Sandbox Code Playgroud)
使用 try_parse:
SELECT try_parse(CloseDate as datetime using 'en-us')
FROM MyTable
(4959 row(s) affected)
SQL Server Execution Times:
CPU time = 719 ms, elapsed time = 718 ms.
Run Code Online (Sandbox Code Playgroud)
后一种情况下的执行计划看起来很无辜:
有没有什么方法可以让我以后更容易地发现罪魁祸首?缓慢的实际来源完全隐藏在视线之外。
关于 SQLOS 的执行模型(RUNNING 状态、RUNNABLE 队列、WAITER 列表),当当前正在进行 RAM 中页面的逻辑读取时,任务的状态是什么?
如果是 WAITER 列表,最流行的等待类型是什么?
我可以以某种方式测量此类操作所需的时间吗?
我知道很多逻辑读取会减慢您的查询速度,很多表/索引扫描(已经位于缓冲池中)会减慢您的查询速度 - 我只想知道它们如何出现在统计信息/dmv 中或如何将其与其他数据区分开来“经典”等待类型。