小编Mar*_*ith的帖子

SQL Server 中的临时表和表变量有什么区别?

这似乎是一个有很多神话和相互冲突的领域。

那么SQL Server中的表变量和本地临时表有什么区别呢?

sql-server t-sql temporary-tables

465
推荐指数
2
解决办法
24万
查看次数

如何在 SQL Server 中将日期和时间与 datetime2 结合起来?

鉴于以下组件

DECLARE @D DATE = '2013-10-13'
DECLARE @T TIME(7) = '23:59:59.9999999'
Run Code Online (Sandbox Code Playgroud)

将它们结合起来以产生DATETIME2(7)具有价值的结果的最佳方法是'2013-10-13 23:59:59.9999999'什么?

有些东西工作,如下表所示。


SELECT @D + @T 
Run Code Online (Sandbox Code Playgroud)

操作数数据类型日期对加法运算符无效。


SELECT CAST(@D AS DATETIME2(7)) + @T 
Run Code Online (Sandbox Code Playgroud)

操作数数据类型 datetime2 对加法运算符无效。


SELECT DATEADD(NANOSECOND,DATEDIFF(NANOSECOND,CAST('00:00:00.0000000' AS TIME),@T),@D)
Run Code Online (Sandbox Code Playgroud)

datediff 函数导致溢出。分隔两个日期/时间实例的日期部分数量太大。尝试将 datediff 与不太精确的日期部分一起使用。

* 可以在 Azure SQL 数据库和 SQL Server 2016 中避免溢出,使用DATEDIFF_BIG.


SELECT CAST(@D AS DATETIME) + @T 
Run Code Online (Sandbox Code Playgroud)

数据类型 datetime 和 time 在 add 运算符中不兼容。


SELECT CAST(@D AS DATETIME) + CAST(@T AS DATETIME)
Run Code Online (Sandbox Code Playgroud)

返回结果但失去精度 2013-10-13 23:59:59.997

sql-server datatypes date time datetime2

55
推荐指数
3
解决办法
6万
查看次数

堆上非聚集索引与聚集索引的性能

这份 2007 年的白皮书比较了单个 select/insert/delete/update 和 range select 语句在组织为聚集索引的表上的性能与在与 CI 相同的键列上组织为具有非聚集索引的堆的表上的性能桌子。

一般来说,聚集索引选项在测试中表现更好,因为只有一种结构需要维护,而且不需要书签查找。

该论文未涵盖的一个潜在有趣案例是堆上的非聚集索引与聚集索引上的非聚集索引之间的比较。在那种情况下,我曾期望堆甚至可能表现得更好,因为一旦在 NCI 叶级 SQL Server 有一个 RID 可以直接跟随,而不需要遍历聚集索引。

有没有人知道在这个领域进行过类似的正式测试,如果有,结果是什么?

sql-server clustered-index

39
推荐指数
3
解决办法
5799
查看次数

使用 XML 阅读器优化计划

从这里执行查询以从默认扩展事件会话中提取死锁事件

SELECT CAST (
    REPLACE (
        REPLACE (
            XEventData.XEvent.value ('(data/value)[1]', 'varchar(max)'),
            '<victim-list>', '<deadlock><victim-list>'),
        '<process-list>', '</victim-list><process-list>')
    AS XML) AS DeadlockGraph
FROM (SELECT CAST (target_data AS XML) AS TargetData
    FROM sys.dm_xe_session_targets st
    JOIN sys.dm_xe_sessions s ON s.address = st.event_session_address
    WHERE [name] = 'system_health') AS Data
CROSS APPLY TargetData.nodes ('//RingBufferTarget/event') AS XEventData (XEvent)
    WHERE XEventData.XEvent.value('@name', 'varchar(4000)') = 'xml_deadlock_report';
Run Code Online (Sandbox Code Playgroud)

在我的机器上完成大约需要 20 分钟。报告的统计数据是

Table 'Worktable'. Scan count 0, logical reads 68121, physical reads 0, read-ahead reads 0, 
         lob logical reads 25674576, lob …
Run Code Online (Sandbox Code Playgroud)

xml sql-server execution-plan database-internals sql-server-2012

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

为什么在这种特定情况下使用表变量的速度是 #temp 表的两倍多?

我正在查看此处的文章 Temporary Tables vs. Table Variables and their Effect on SQL Server Performance and on SQL Server 2008 能够重现与 2005 中显示的结果类似的结果。

当执行只有 10 行的存储过程(定义如下)时,表变量 version out 执行临时表 version 的两倍以上。

我清除了过程缓存并运行了两个存储过程 10,000 次,然后再重复该过程 4 次。结果如下(每批时间以毫秒为单位)

T2_Time     V2_Time
----------- -----------
8578        2718      
6641        2781    
6469        2813   
6766        2797
6156        2719
Run Code Online (Sandbox Code Playgroud)

我的问题是:表变量版本性能更好的原因什么?

我做了一些调查。例如查看性能计数器

SELECT cntr_value
from sys.dm_os_performance_counters
where counter_name = 'Temp Tables Creation Rate';
Run Code Online (Sandbox Code Playgroud)

确认在这两种情况下,临时对象都按预期在第一次运行后被缓存,而不是每次调用都从头开始创建。

类似地跟踪Profiler 中的Auto Stats, SP:Recompile,SQL:StmtRecompile事件(下面的屏幕截图)显示这些事件仅发生一次(在第一次调用#temp表存储过程时),其他 9,999 次执行不会引发任何这些事件。(表变量版本没有得到任何这些事件) …

sql-server temporary-tables

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

从列表中查找表中不存在的 ID

假设我有以下架构和数据:

create table images(
  id int not null
);

insert into images values(1), (2), (3), (4), (6), (8);
Run Code Online (Sandbox Code Playgroud)

我想执行如下查询:

select id from images where id not exists in(4, 5, 6);
Run Code Online (Sandbox Code Playgroud)

但这不起作用。上面的情况应该返回5,因为它不存在于表记录中。

postgresql if-not-exists

33
推荐指数
3
解决办法
6万
查看次数

为什么在这些计划中对唯一索引进行(相同)1000 次搜索的估计成本不同?

在下面的查询中,估计两个执行计划对唯一索引执行 1,000 次搜索。

查找是由对同一源表的有序扫描驱动的,因此看起来最终应该以相同的顺序查找相同的值。

两个嵌套循环都有 <NestedLoops Optimized="false" WithOrderedPrefetch="true">

任何人都知道为什么这个任务在第一个计划中的成本为 0.172434,而在第二个计划中为 3.01702?

(问题的原因是第一个查询被建议作为优化,因为计划成本明显低得多。它实际上在我看来好像它做了更多的工作,但我只是试图解释这种差异.. .)

设置

CREATE TABLE dbo.Target(KeyCol int PRIMARY KEY, OtherCol char(32) NOT NULL);

CREATE TABLE dbo.Staging(KeyCol int PRIMARY KEY, OtherCol char(32) NOT NULL); 

INSERT INTO dbo.Target
SELECT TOP (1000000) ROW_NUMBER() OVER (ORDER BY @@SPID), LEFT(NEWID(),32)
FROM master..spt_values v1,  
     master..spt_values v2;

INSERT INTO dbo.Staging
SELECT TOP (1000) ROW_NUMBER() OVER (ORDER BY @@SPID), LEFT(NEWID(),32)
FROM master..spt_values v1;
Run Code Online (Sandbox Code Playgroud)

查询 1 “粘贴计划”链接

WITH T
     AS (SELECT *
         FROM   Target AS T
         WHERE  T.KeyCol …
Run Code Online (Sandbox Code Playgroud)

sql-server optimization sql-server-2014

28
推荐指数
3
解决办法
628
查看次数

如何有效地检查多列上的 EXISTS?

这是我定期遇到的一个问题,但尚未找到好的解决方案。

假设如下表结构

CREATE TABLE T
(
A INT PRIMARY KEY,
B CHAR(1000) NULL,
C CHAR(1000) NULL
)
Run Code Online (Sandbox Code Playgroud)

并且要求是确定可空列中的任何一个BC实际上是否包含任何NULL值(如果是,则是哪个(些))。

还假设该表包含数百万行(并且没有可用的列统计信息可以查看,因为我对此类查询的更通用解决方案感兴趣)。

我可以想到几种方法来解决这个问题,但都有弱点。

两个单独的EXISTS声明。这将具有允许查询在NULL发现a 后尽早停止扫描的优点。但是如果两列实际上都不包含NULLs,那么将导致两次完整扫描。

单一聚合查询

SELECT 
    MAX(CASE WHEN B IS NULL THEN 1 ELSE 0 END) AS B,
    MAX(CASE WHEN C IS NULL THEN 1 ELSE 0 END) AS C
FROM T
Run Code Online (Sandbox Code Playgroud)

这可以同时处理两列,因此最坏的情况是一次完整扫描。缺点是即使它NULL在查询的很早的时候在两列中都遇到了 a ,最终仍会扫描整个表的其余部分。

用户变量

可以想到第三种方式来做到这一点

BEGIN TRY
DECLARE @B INT, @C INT, @D …
Run Code Online (Sandbox Code Playgroud)

performance sql-server

26
推荐指数
2
解决办法
11万
查看次数

为什么搜索 LIKE N'%?%' 匹配任何 Unicode 字符并且 = N'?' 匹配很多?

DECLARE @T TABLE(
  Col NCHAR(1));

INSERT INTO @T
VALUES      (N'A'),
            (N'B'),
            (N'C'),
            (N'?'),
            (N'?'),
            (N'?');
Run Code Online (Sandbox Code Playgroud)
SELECT *
FROM   @T
WHERE  Col LIKE N'%?%'
Run Code Online (Sandbox Code Playgroud)

退货

Col
A
B
C
?
?
?
Run Code Online (Sandbox Code Playgroud)
SELECT *
FROM   @T
WHERE  Col = N'?' 
Run Code Online (Sandbox Code Playgroud)

退货

Col
?
?
?
Run Code Online (Sandbox Code Playgroud)

使用下面的生成每个可能的双字节“字符”显示=版本匹配其中的 21,229 个和LIKE N'%?%'所有版本(我尝试了一些非二进制排序规则,结果相同)。

WITH T(I, N)
AS 
(
SELECT TOP 65536 ROW_NUMBER() OVER (ORDER BY @@SPID),
                 NCHAR(ROW_NUMBER() OVER (ORDER BY @@SPID))
FROM master..spt_values v1, 
     master..spt_values v2
)
SELECT I, N 
FROM …
Run Code Online (Sandbox Code Playgroud)

sql-server like unicode sql-server-2016

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

ON 子句的位置实际上是什么意思?

正常的JOIN ... ON ...语法是众所周知的。但也可以将ON子句JOIN与其对应的分开放置。这在实践中很少见,在教程中找不到,我也没有找到任何网络资源甚至提到这是可能的。

这是一个可以玩的脚本:

SELECT *
INTO #widgets1
FROM (VALUES (1), (2), (3)) x(WidgetID)


SELECT *
INTO #widgets2
FROM (VALUES (1, 'SomeValue1'), (2, 'SomeValue2'), (3, 'SomeValue3')) x(WidgetID, SomeValue)

SELECT *
INTO #widgetProperties
FROM (VALUES
    (1, 'a'), (1, 'b'),
    (2, 'a'), (2, 'b'))
x(WidgetID, PropertyName)


--q1
SELECT w1.WidgetID, w2.SomeValue, wp.PropertyName
FROM #widgets1 w1
LEFT JOIN #widgets2 w2 ON w2.WidgetID = w1.WidgetID
LEFT JOIN #widgetProperties wp ON w2.WidgetID = wp.WidgetID AND wp.PropertyName = …
Run Code Online (Sandbox Code Playgroud)

sql-server t-sql

23
推荐指数
2
解决办法
2283
查看次数