通用表表达式 (CTE) 和临时表有什么区别?我什么时候应该使用一个?
CTE
WITH cte (Column1, Column2, Column3)
AS
(
SELECT Column1, Column2, Column3
FROM SomeTable
)
SELECT * FROM cte
Run Code Online (Sandbox Code Playgroud)
临时表
SELECT Column1, Column2, Column3
INTO #tmpTable
FROM SomeTable
SELECT * FROM #tmpTable
Run Code Online (Sandbox Code Playgroud) 我正在查看此处的文章 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 次执行不会引发任何这些事件。(表变量版本没有得到任何这些事件) …
我试图理解为什么使用表变量会阻止优化器使用索引查找然后书签查找与索引扫描。
填充表:
CREATE TABLE dbo.Test
(
RowKey INT NOT NULL PRIMARY KEY,
SecondColumn CHAR(1) NOT NULL DEFAULT 'x',
ForeignKey INT NOT NULL
)
INSERT dbo.Test
(
RowKey,
ForeignKey
)
SELECT TOP 1000000
ROW_NUMBER() OVER (ORDER BY (SELECT 0)),
ABS(CHECKSUM(NEWID()) % 10)
FROM sys.all_objects s1
CROSS JOIN sys.all_objects s2
CREATE INDEX ix_Test_1 ON dbo.Test (ForeignKey)
Run Code Online (Sandbox Code Playgroud)
使用单个记录填充表变量,并尝试通过搜索外键列来查找主键和第二列:
DECLARE @Keys TABLE (RowKey INT NOT NULL)
INSERT @Keys (RowKey) VALUES (10)
SELECT
t.RowKey,
t.SecondColumn
FROM
dbo.Test t
INNER JOIN
@Keys k
ON
t.ForeignKey = …Run Code Online (Sandbox Code Playgroud) sql-server optimization sql-server-2008-r2 user-defined-table-type bookmark-lookup
给定一个简单的三表连接,当包含 ORDER BY 时,即使没有返回行,查询性能也会发生巨大变化。实际问题场景需要 30 秒才能返回零行,但在不包括 ORDER BY 时是即时的。为什么?
SELECT *
FROM tinytable t /* one narrow row */
JOIN smalltable s on t.id=s.tinyId /* one narrow row */
JOIN bigtable b on b.smallGuidId=s.GuidId /* a million narrow rows */
WHERE t.foreignId=3 /* doesn't match */
ORDER BY b.CreatedUtc /* try with and without this ORDER BY */
Run Code Online (Sandbox Code Playgroud)
我知道我可以在 bigtable.smallGuidId 上建立索引,但是,我相信在这种情况下这实际上会使情况变得更糟。
这是创建/填充表以进行测试的脚本。奇怪的是,smalltable 有一个 nvarchar(max) 字段似乎很重要。我使用 guid 加入 bigtable 似乎也很重要(我猜这使它想要使用哈希匹配)。
CREATE TABLE tinytable
(
id INT PRIMARY KEY IDENTITY(1, 1),
foreignId …Run Code Online (Sandbox Code Playgroud) 我有一个大的用户定义的表类型变量,它有 129 列。我将一次在这个表变量中存储大约 2000-3000 条记录,并将其传递给各种存储过程和函数以获取附加数据并进行修改。然后,这些附加数据和新修改将存储在相同类型的新表变量中,并通过OUTPUT参数返回到源存储过程。(这是因为表类型参数只能作为READONLY.)
这是我的伪代码:
SP1
@tmp tableType
{
INSERT @tmp EXEC
SP2 (@tmp)
INSERT @tmp EXEC
SP3 (@tmp)
}
Run Code Online (Sandbox Code Playgroud)
我应该使用 a@table_variable还是#temp_table?
SQL Server 2019。这是 xml 计划要点的链接。
您好,我花了很长时间才明白为什么当它找不到包含其中一种状态的记录时,为什么这个查询需要 0.02 秒才能执行。当它找到具有包含状态之一的记录时,它往往要快得多。我猜这是因为一旦找到匹配的 1 行,查询就会停止。
SELECT TOP 1 IDNum,
FORMAT(Date, 'M/d/yy') AS theDate,
Status,
Rate
FROM theDB
INNER JOIN DomainTable
ON theDB.IDNum = DomainTable.IDNum
WHERE DomainIP = '127.0.0.1'
AND status IN ( 'Active', 'To ReActivate', 'To Deactivate', 'Deactivate ASAP',
'SUSPENDED', 'SUSPENDED X', 'SUSPENDED Y', 'SUSPENDED Z' )
ORDER BY theDB.IDNum DESC
Run Code Online (Sandbox Code Playgroud)
(DomainIP属于DomainTable,其他属于DB)
在执行计划中,最大的成本是 TOP N SORT,占 33% 聚集索引搜索占 29% 对 DomainTable 的键查找使用了 29% 在 DomainTable 上搜索 IP 的索引是 9%
我的问题是:
有没有办法让TOP N不那么重?
0.02 …
是否可以在 SQL Server 2012 中执行类似于以下操作?
IF EXISTS (
WITH DATA AS (
SELECT *,
ROW_NUMBER() OVER(PARTITION BY column ORDER BY Column) AS rn
FROM table )
SELECT *
FROM DATA
WHERE rn = 2 )
BEGIN
...
END
Run Code Online (Sandbox Code Playgroud)
我尝试使用此语法并收到错误消息。如果这是不可能的,使用临时表是实现此目的的最佳方法吗?
我在 SQL Server 中有一个表,如下所示:
Id |Version |Name |date |fieldA |fieldB ..|fieldZ
1 |1 |Foo |20120101|23 | ..|25334123
2 |2 |Foo |20120101|23 |NULL ..|NULL
3 |2 |Bar |20120303|24 |123......|NULL
4 |2 |Bee |20120303|34 |-34......|NULL
Run Code Online (Sandbox Code Playgroud)
我正在研究一个存储过程来区分,它需要输入数据和版本号。输入数据包含从 Name up 到 fieldZ 的列。大多数字段列预计为NULL,即每行通常只有前几个字段的数据,其余为NULL。名称、日期和版本构成了表上的唯一约束。
对于给定的版本,我需要对输入的与该表相关的数据进行比较。每一行都需要区分——一行由名称、日期和版本标识,字段列中任何值的任何更改都需要显示在差异中。
更新:所有字段都不需要是十进制类型。其中一些可能是 nvarchars。我更希望 diff 发生而不转换类型,尽管 diff 输出可以将所有内容转换为 nvarchar,因为它仅用于显示目的。
假设输入如下,请求的版本为2,:
Name |date |fieldA |fieldB|..|fieldZ
Foo |20120101|25 |NULL |.. |NULL
Foo |20120102|26 |27 |.. |NULL
Bar |20120303|24 |126 |.. |NULL
Baz |20120101|15 |NULL |.. |NULL
Run Code Online (Sandbox Code Playgroud)
差异需要采用以下格式:
name |date |field |oldValue |newValue
Foo |20120101|FieldA …Run Code Online (Sandbox Code Playgroud) 有什么方法可以识别哪个存储过程在 tempDB 中创建表变量?
我正在查看 sys.dm_db_index_operational_stats 中的 forward_fetch_count,我们有几个表的计数非常大(最大的超过 1.33 亿)。表名以 # 后跟 8 个十六进制字符的形式出现在 tempDB 中。有没有办法将其追溯到原始流程,以便我们修复它?
我们在 Linux 上运行 SQL 2019。
谢谢,埃文
我有以下过程,每天调用超过一百万次,我认为可以对其进行调整以更好地使用资源。
ALTER PROCEDURE [DenormV2].[udpProductTaxRateGet]
(
@itemNo varchar ( 20 ),
@calculateDate datetime,
@addressLine1 nvarchar( 50 ),
@addressLine2 nvarchar( 50 ),
@addressLine3 nvarchar( 50 ),
@addressLine4 nvarchar( 50 ),
@addressLine5 nvarchar( 50 ),
@addressLine6 nvarchar( 50 ),
@postalCode nvarchar( 20 ),
@countryCode varchar( 2 ),
@addressFormatID int
)
WITH EXECUTE AS 'webUserWithRW'
AS
--see Bocss2.dbo.[fnGetProductTax] for equivalent logic and comments in Bocss
DECLARE @Addresses TABLE (TaxRegionId int NOT NULL)
INSERT INTO @Addresses(TaxRegionId)
SELECT DISTINCT TaxRegionId
FROM dbo.[ShipTaxAddress]
WHERE [CountryCode] = @countryCode …Run Code Online (Sandbox Code Playgroud) performance sql-server-2005 sql-server execution-plan table-variable query-performance