Sql server 2008 如何定义非聚集索引的列顺序
我编写了一个子查询,如下所示:Sql server 2008 如何定义非聚集索引的列顺序,sql-server-2008,non-clustered-index,Sql Server 2008,Non Clustered Index,我编写了一个子查询,如下所示: select top 1 A from my_table where B = some_joined_value_from_outer_query order by C desc 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
select top 1 A
from my_table
where B = some_joined_value_from_outer_query
order by C desc
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
我想创建一个非聚集索引来提高这方面的性能
这里有3个问题:
top 1
和order by desc
),这样是否可以提高性能编辑: 以下是查询(数据同步过程的一部分): (A) (B) 由于A不在
的WHERE
或ORDER BY
中,因此在INCLUDE
d列的列表中可能就足够了,因为它只是“随行”而不必是钥匙的一部分
(C)
没有更多的上下文就无法回答。为什么只包含子查询,然后询问我们看不到的外部查询
EDIT关于正在进行的与@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),则计划更为相似。但这也意味着分区BY是不必要的,并且需要进行一些匹配,以将外部查询也限制为B值。然而,我的观点仍然是,虽然对于问题中的特定查询,索引中每列的排序方向可能对计划影响不大,但并非所有可能使用相同索引的查询都是如此。(A) (B) 由于A不在
的WHERE
或ORDER BY
中,因此在INCLUDE
d列的列表中可能就足够了,因为它只是“随行”而不必是钥匙的一部分
(C)
没有更多的上下文就无法回答。为什么只包含子查询,然后询问我们看不到的外部查询
EDIT关于正在进行的与@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),则计划更为相似。但这也意味着分区BY是不必要的,并且需要进行一些匹配,以将外部查询也限制为B值。然而,我的观点仍然是,虽然对于问题中的特定查询,索引中每列的排序方向可能对计划影响不大,但并非所有可能使用相同索引的查询都是如此。顺序确实重要。第一级的列是最重要的
索引的选择完全基于第一列。只有在查询中使用索引中列出的第一列时,才会考虑使用索引。所以,若第一列并没有匹配项,并且查询的JOIN、ORDER BY或WHERE子句中使用了列,那个么索引将被完全忽略 顺序很重要。第一级的列是最重要的
索引的选择完全基于第一列。只有在查询中使用索引中列出的第一列时,才会考虑使用索引。所以,若第一列并没有匹配项,并且查询的JOIN、ORDER BY或WHERE子句中使用了列,那个么索引将被完全忽略 您可以这样重写它:
select top 1 A
from my_table
where B = some_joined_value_from_outer_query
order by C desc
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
但是子查询实际上可能更快(也可能不会)
在我的博客中查看此条目:
- 您可以这样重写它:
select top 1 A
from my_table
where B = some_joined_value_from_outer_query
order by C desc
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
但是子查询实际上可能更快(也可能不会)
在我的博客中查看此条目:
C ASC
的行为也一样。关于子查询,它在外部查询的选择列表中使用。因此,它必须返回一个结果(或NULL).@Quassnoi虽然对于计划本身为true,但索引的定义更好地描述了它的意图(它是为满足查询而构建的)。你确定这种行为适用于大量相同的B值吗?@Keon是的,我理解,但我们不能只看子查询,在没有更多上下文的情况下说“哦,这会更快”。因此,如果你想问一个关于如何使整个查询更好的问题,请发布整个查询。谢谢你完整的回答。我有解释过的索引。不过,我花了1个多小时来选择大约60万条记录,我认为这些记录可以改进。已经发布了完整的查询,因此您可能会看到一些改进…对于这个查询,C ASC
的行为将与此相同。关于子查询,它用于外部查询的选择列表中。因此,它必须返回一个结果(或NULL).@Quassnoi虽然对于计划本身为true,但索引的定义更好地描述了它的意图(它是为满足查询而构建的)。你确定这种行为适用于B的大量相同值吗?@Keon是的,我理解