在SQL中选择单行的最快方法是什么? (SQL Server)

时间:2019-05-06 15:17:33

标签: sql sql-server performance query-performance sqlperformance

我知道从表中选择单行的两种不同方式(没有保证单条记录的where子句)。

SELECT TOP 1 [Id]
FROM [MyTable]
ORDER BY [Id] ASC

SELECT [Id]
FROM [MyTable]
ORDER BY [Id] ASC
OFFSET 0 ROWS
FETCH NEXT 1 ROWS ONLY

从统计意义上讲,其中哪些更快? ([Id]是主键)

还是我不知道的这两种方法有更快的替代方法?

1 个答案:

答案 0 :(得分:1)

计划之间没有区别。最高语法和按语法排序将使用相同的查询计划。但是,在某些情况下,可能会有一种更好的方法来查询此信息。

以下查询使用主键在表中伪造100,000行数据。然后使用前1种语法,offset fetch语法并最后使用where子句直接搜索来填充数据。

declare @t table 

(
    id int primary key clustered,
    sometext nvarchar(150)
);

declare @runs int = 1;

while @runs<=100000
    begin
        insert @t (id, sometext)
        values
        (@runs, 'abc123');
        select @runs=@runs+1;
    end


SELECT TOP 1 [Id]
FROM @t
ORDER BY [Id] ASC;


SELECT [Id]
FROM @t
ORDER BY [Id] ASC
OFFSET 0 ROWS
FETCH NEXT 1 ROWS ONLY;


select id from @t where id=1;

Query Plans

该图像随后显示3个查询计划。前两个查询显示完全相同的计划,即使用主键进行的索引扫描。但是,第三个带有where子句的查询正在显示索引查找。这是因为如果您已经知道要查找的堆中的什么位置,则无需扫描整个数据集即可找到顶部。

索引查找的性能往往优于扫描,尤其是在具有许多不同数据类型列的大型表中。在这种非常简单的表结构和100,000行的情况下,当前批次中的成本完全相同(17%)。

对于更大的数据集,我建议采用一种类似以下的方法。

declare @id int = 0;
select @id=min(id) from @t;

然后,您可以在这样的where子句中使用此id变量。

select id, sometext from @t where id=@id;

哪个表可以使用索引查找计划,而该表的行数更多,并且比该测试更复杂。