DROP TABLE IF EXISTS #EmptyTable, #BigTable
CREATE TABLE #EmptyTable(A int);
CREATE TABLE #BigTable(A int);
INSERT INTO #BigTable
SELECT TOP 10000000 CRYPT_GEN_RANDOM(3)
FROM sys.all_objects o1,
sys.all_objects o2,
sys.all_objects o3;
Run Code Online (Sandbox Code Playgroud)
WITH agg
AS (SELECT DISTINCT a
FROM #BigTable)
SELECT *
FROM #EmptyTable E
INNER HASH JOIN agg B
ON B.A = E.A;
Run Code Online (Sandbox Code Playgroud)
这是我今天之前没有注意到的现象的简化再现。我对内部散列连接的期望是,如果构建输入为空,则不应执行探测端,因为连接不会返回任何行。上面的示例与此相反,并从表中读取了 1000 万行。这使查询的执行时间增加了 2.196 秒 (99.9%)。
OPTION (MAXDOP 1)执行计划从#BigTable. 该ActualExecutions是0对哈希连接内所有的运营商。SELECT * FROM #EmptyTable E INNER …在我发布关于缺少相关文档的连接项目之前,有人会确认我不是在这里遗漏了什么吗?
在format被列为字符串函数的文档页面上:
“所有内置字符串函数都是确定性的。” -字符串函数 (Transact-SQL)
format在相关页面上也没有提到不确定性:
但是,在尝试创建持久计算列时:
create table t (date_col date);
insert into t values (getdate());
alter table t add date_formatted_01 as format(date_col,'YYYY') persisted;
Run Code Online (Sandbox Code Playgroud)
返回以下错误:
无法保留表 't' 中的计算列 'date_formatted_01',因为该列是不确定的。
该文件指出
如果未提供文化参数,则使用当前会话的语言。
但添加文化论点并不会改变事情
这也失败
alter table t add date_formatted_02 as format(date_col, 'd', 'en-US' ) persisted
Run Code Online (Sandbox Code Playgroud)
reextester 演示:http ://rextester.com/ZMS22966
dbfiddle.uk 演示:http ://dbfiddle.uk/?rdbms=sqlserver_next&fiddle=7fc57d1916e901cb561b551af144aed6
在T-SQL.
任务:
问题: 解决这个问题最有效的方法是什么?如果循环是正确的,还有改进的余地吗?
我使用了一个循环和 # 临时表,这里是我的解决方案:
set rowcount 0
-- THE SOURCE TABLE "LINE" HAS THE SAME SCHEMA AS #RESULT AND #TEMP
use Northwind
go
declare @sum int
declare @curr int
set @sum = 0
declare @id int
IF OBJECT_ID('tempdb..#temp','u') IS NOT NULL
DROP TABLE #temp
IF OBJECT_ID('tempdb..#result','u') IS NOT NULL
DROP TABLE #result
create table #result(
id int not null,
[name] varchar(255) not null,
weight int not null, …Run Code Online (Sandbox Code Playgroud) 长话短说,我们正在使用非常大的人员表中的值更新小型人员表。在最近的测试中,此更新需要大约 5 分钟才能运行。
我们偶然发现了看似最愚蠢的优化方法,但它似乎完美无缺!相同的查询现在可以在不到 2 分钟的时间内运行并完美地产生相同的结果。
这是查询。最后一行被添加为“优化”。为什么查询时间急剧减少?我们错过了什么吗?这会导致将来出现问题吗?
UPDATE smallTbl
SET smallTbl.importantValue = largeTbl.importantValue
FROM smallTableOfPeople smallTbl
JOIN largeTableOfPeople largeTbl
ON largeTbl.birth_date = smallTbl.birthDate
AND DIFFERENCE(TRIM(smallTbl.last_name),TRIM(largeTbl.last_name)) = 4
AND DIFFERENCE(TRIM(smallTbl.first_name),TRIM(largeTbl.first_name)) = 4
WHERE smallTbl.importantValue IS NULL
-- The following line is "the optimization"
AND LEFT(TRIM(largeTbl.last_name), 1) IN ('a','à','á','b','c','d','e','è','é','f','g','h','i','j','k','l','m','n','o','ô','ö','p','q','r','s','t','u','ü','v','w','x','y','z','æ','ä','ø','å')
Run Code Online (Sandbox Code Playgroud)
技术说明:我们知道要测试的字母列表可能需要更多的字母。我们也意识到使用“DIFFERENCE”时明显的误差幅度。
查询计划(常规): https : //www.brentozar.com/pastetheplan/?
id = rypV84y7V 查询计划(带“优化”):https : //www.brentozar.com/pastetheplan/?id=r1aC2my7E
我最近继承了一个使用日期分区的项目,其中每日计划任务实现了过去 30 天和未来 60 天的滑动窗口方案。
实际上,插入的数据SYSUTCDATETIME()用于分区列,因此未来的 60 个分区始终为空。
这是一个需要解决的问题还是我应该让睡狗撒谎?
在阅读这篇关于 SQL Server 中的计划缓存的文章时,我发现了一个我不知道的花絮:
...为了重用,批处理引用的对象不需要名称解析。例如,Sales.SalesOrderDetail 不需要名称解析,而 SalesOrderDetail 则需要,因为在多个架构中可能存在名为 SalesOrderDetail 的表。通常,由两部分组成的对象名称(即 schema.object)为计划重用提供了更多机会。
我正在寻找关于使用两部分对象名称的重要性的一些说明,因为“通常,两部分对象名称为计划重用提供了更多机会。”,但它首先说这是必要的。
更具体地说,我处理的大多数存储过程都在 dbo 模式中,并且只引用 dbo 对象,而没有指定 dbo 前缀。即使所有内容都使用默认模式,这些是否无法重用缓存的查询计划?
我听到了关于这方面的混合信息,希望得到权威或专家的意见。
如果我有多个LEFT OUTER JOINs ,每个都依赖于最后一个,嵌套它们更好吗?
对于一个人为的例子,JOINtoMyParent取决于JOINto MyChild:http :
//sqlfiddle.com/#!3/31022/5
SELECT
{columns}
FROM
MyGrandChild AS gc
LEFT OUTER JOIN
MyChild AS c
ON c.[Id] = gc.[ParentId]
LEFT OUTER JOIN
MyParent AS p
ON p.[id] = c.[ParentId]
Run Code Online (Sandbox Code Playgroud)

与http://sqlfiddle.com/#!3/31022/7相比
SELECT
{columns}
FROM
MyGrandChild AS gc
LEFT OUTER JOIN
(
MyChild AS c
LEFT OUTER JOIN
MyParent AS p
ON p.[id] = c.[ParentId]
)
ON c.[Id] = gc.[ParentId]
Run Code Online (Sandbox Code Playgroud)

如上所示,这些在 SS2k8 中产生不同的查询计划
我有一个包含以下内容的示例数据文件,并使用 UTF8 编码保存。
\noab~opqr\n\xc3\xb6ab~\xc3\xb6pqr\n\xc3\xb6ab~\xc3\xb6pqr\nRun Code Online (Sandbox Code Playgroud)\n该文件的格式是固定宽度,第 1 至第 3 列各分配 1 个字符,第 4 列保留 5 个字符。
\n我创建了一个 XML 格式文件,如下所示
\n<?xml version = "1.0"?> \n<BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> \n <RECORD> \n <FIELD xsi:type="CharFixed" ID="Col1" LENGTH="1"/> \n <FIELD xsi:type="CharFixed" ID="Col2" LENGTH="1"/> \n <FIELD xsi:type="CharFixed" ID="Col3" LENGTH="1"/> \n <FIELD xsi:type="CharFixed" ID="Col4" LENGTH="5"/> \n <FIELD xsi:type="CharTerm" ID="LINE_BREAK" TERMINATOR="\\n"/> \n </RECORD> \n <ROW> \n <COLUMN SOURCE="Col1" NAME="Col1" xsi:type="SQLNVARCHAR"/> \n <COLUMN SOURCE="Col2" NAME="Col2" xsi:type="SQLNVARCHAR"/> \n <COLUMN SOURCE="Col3" NAME="Col3" xsi:type="SQLNVARCHAR"/> \n <COLUMN SOURCE="Col4" NAME="Col4" xsi:type="SQLNVARCHAR"/> …Run Code Online (Sandbox Code Playgroud) 大学 SQL 课程,使用 John J. Patrick 所著的“SQL Fundamentals”一书。在第三章中,他谈到使用“常量表”向 select 语句添加列,其中所有行都具有相同的值。
例如,如果您有表“字符”,如下所示:
first_name last_name dept_code
----------- ---------- -------------------
Fred Flintstone ROCKS
Barney Rubble ROCKS
Wilma Flintstone FACEPALMING_AT_FRED
Run Code Online (Sandbox Code Playgroud)
并且您想要一个 SELECT 向所有行添加值为“BEDROCK”的列“hometown”,他建议在数据库中创建第二个表“temp”,
hometown
--------
BEDROCK
Run Code Online (Sandbox Code Playgroud)
然后做
SELECT first_name, last_name, dept_code, hometown FROM characters, temp
Run Code Online (Sandbox Code Playgroud)
这个想法是避免将字符串常量放在 SELECT 语句中,并且如果您有很多需要相同常量的 SELECT,更新一个表比更新 50 个查询更容易。
问题是,过去 15 年来我一直在使用 SQL 数据库,但我从未见过这种结构。它是我刚刚错过的完全常见的东西,还是在这个任务结束后我可以从我的记忆中抹去的东西?
sql-server ×7
encoding ×1
join ×1
openrowset ×1
optimization ×1
parallelism ×1
partitioning ×1
performance ×1
t-sql ×1