更新 2014-12-18
由于对主要问题的压倒性回答是“否”,更有趣的回答集中在第 2 部分,如何使用明确的ORDER BY. 尽管我已经标记了一个答案,但如果有性能更好的解决方案,我也不会感到惊讶。
原来的
出现这个问题是因为我能找到的针对特定问题的唯一极快的解决方案只能在没有ORDER BY子句的情况下起作用。下面是产生问题所需的完整 T-SQL,以及我提出的解决方案(我使用的是 SQL Server 2008 R2,如果这很重要。)
--Create Orders table
IF OBJECT_ID('tempdb..#Orders') IS NOT NULL DROP TABLE #Orders
CREATE TABLE #Orders
(
OrderID INT NOT NULL IDENTITY(1,1)
, CustID INT NOT NULL
, StoreID INT NOT NULL
, Amount FLOAT NOT NULL
)
CREATE CLUSTERED INDEX IX ON #Orders (StoreID, Amount DESC, CustID)
--Add 1 million rows w/ 100K Customers each of whom had 10 orders
;WITH
Cte0 …Run Code Online (Sandbox Code Playgroud) 通常,出于所有标准原因,我建议不要使用连接提示。然而,最近我发现了一种模式,我几乎总能找到一个强制循环连接来表现更好。事实上,我开始使用和推荐它,以至于我想获得第二意见以确保我没有遗漏任何东西。下面是一个有代表性的场景(生成示例的非常具体的代码在最后):
--Case 1: NO HINT
SELECT S.*
INTO #Results
FROM #Driver AS D
JOIN SampleTable AS S ON S.ID = D.ID
--Case 2: LOOP JOIN HINT
SELECT S.*
INTO #Results
FROM #Driver AS D
INNER LOOP JOIN SampleTable AS S ON S.ID = D.ID
Run Code Online (Sandbox Code Playgroud)
SampleTable 有 100 万行,它的 PK 是 ID。
临时表 #Driver 只有一列、ID、没有索引和 50K 行。
我始终发现以下内容:
案例 1:
SampleTable
Hash Join
上的NO HINT索引扫描更高的持续时间(平均 333ms)
更高的 CPU(平均 331ms)
更低的逻辑读取(4714)
案例 2:LOOP JOIN HINT
索引在
SampleTable
循环中搜索 加入
较低的持续时间(平均 204 毫秒,减少 …
当我查看执行计划时,我经常将“估计行数”与“实际行数”进行比较,寻找差异。例如,当我将鼠标悬停在下图中底部的箭头上时,估计值为 1,实际值为 200,因此乍一看似乎是一个糟糕的估计。

然而,我开始怀疑这是否真的只是一次执行的估计。当我将鼠标悬停在寻求获得更多细节上时,我看到有 200 次处决,估计为 199.98。所以如果我的预感是正确的,估计实际上已经死了。

任何人都可以为我确认是否是这种情况?如果是这样,我是唯一一个认为这是令人难以置信的误导的人吗(尤其是当鼠标悬停在箭头上时)?如果有帮助,这里是设置和重现上述计划的脚本:
-- Setup: Create 2 tables with 100K rows each.
CREATE TABLE T1(Id int NOT NULL PRIMARY KEY, X INT NOT NULL)
CREATE TABLE T2(Id int NOT NULL PRIMARY KEY)
CREATE INDEX Ix ON T1 (X, Id)
;WITH
Pass0 AS (SELECT 1 AS C UNION ALL SELECT 1), --2 rows
Pass1 AS (SELECT 1 AS C FROM Pass0 AS A, Pass0 AS B),--4 rows
Pass2 AS (SELECT 1 AS C FROM Pass1 AS …Run Code Online (Sandbox Code Playgroud)