我写了一个像这样的子查询:
select top 1 A
from my_table
where B = some_joined_value_from_outer_query
order by C desc
我想创建一个非聚集索引,以提高此部分的性能。
这里有3个问题:
top 1
和order by desc
)并且可以改善性能吗?修改 这是查询(数据同步过程的一部分):
SELECT ProductId, (
SELECT Id
FROM [Order]
WHERE Number = (
SELECT TOP 1 OrderNumber
FROM OtherDatabase..ReferenceTable
WHERE ProductNumber = Product.Number
ORDER BY [Date] DESC)
) AS OrderId
FROM Product
答案 0 :(得分:4)
(A)
CREATE NONCLUSTERED INDEX foo ON dbo.my_table(B, C DESC) INCLUDE (A);
(B)
由于A不在WHERE
或ORDER BY
,因此它可能只在INCLUDE
d列的列表中,因为它只是“沿途”并且不是必需的成为关键的一部分。
(C)
没有更多背景,无法回答。为什么你只要包含子查询然后询问我们看不到的外部查询?
编辑关于与@Quassnoi的持续对话,我只想快速演示非聚集索引中的尾随列的排序方向特定查询使用的计划有很大差异。让我们采取以下设计的例子:
CREATE TABLE dbo.foo1(A INT, B INT, C INT);
CREATE NONCLUSTERED INDEX foo1x ON dbo.foo1(B, C) INCLUDE(A);
CREATE TABLE dbo.foo2(A INT, B INT, C INT);
CREATE NONCLUSTERED INDEX foo2x ON dbo.foo2(B, C DESC) INCLUDE(A);
INSERT dbo.foo1 SELECT TOP (500000) c.[object_id], c.[object_id], -1*c.[object_id]
FROM sys.all_columns AS c CROSS JOIN sys.all_objects
ORDER BY c.[object_id];
INSERT dbo.foo2 SELECT TOP (500000) c.[object_id], c.[object_id], -1*c.[object_id]
FROM sys.all_columns AS c CROSS JOIN sys.all_objects
ORDER BY c.[object_id];
现在,让我们运行这两个提议的查询并检查计划:
SELECT A
FROM (
SELECT A, ROW_NUMBER() OVER (PARTITION BY B ORDER BY C DESC) RN
FROM dbo.foo1
) q
WHERE rn = 1;
SELECT A
FROM (
SELECT A, ROW_NUMBER() OVER (PARTITION BY B ORDER BY C DESC) RN
FROM dbo.foo2
) q
WHERE rn = 1;
这是针对dbo.foo1(其中C是ASC)的查询计划:
我提到的那种:
这是针对dbo.foo2(其中C是DESC)的查询计划:
现在,如果向内部查询添加WHERE子句(例如WHERE B = -1024577103),则计划更相似。但是那也意味着PARTITION BY是不必要的,并且需要进行一些匹配以将外部查询限制为B的值。但是我的观点仍然是,对于问题中的特定查询,索引中每列的排序方向可能对计划几乎没有影响,但对于所有可以使用相同索引的查询都不是这样。
答案 1 :(得分:0)
订单确实很重要。第一顺序的列是最重要的。
索引的选择完全基于第一列。仅当在查询中使用索引中列出的第一列时,才考虑使用索引。因此,如果第一列没有匹配,并且在查询的JOIN,ORDER BY或WHERE子句中使用了列,则完全忽略index。
答案 2 :(得分:0)
你可以像这样重写它:
SELECT m.a
FROM (
SELECT m.a, ROW_NUMBER() OVER (PARTITION BY m.b ORDER BY m.c DESC) RN
FROM outer_table o
JOIN my_table m
ON m.b = o.b
) q
WHERE rn = 1
但子查询实际上可能更快(或可能不会)。
请参阅我的博客中的此条目: