select * from <table_name>;
我想只显示第100到第200行.
我想了解这是如何在内部发生的.数据库是否将所有记录从磁盘提取到内存中,并向查询客户端发送回第100行到第400行?或者是否存在任何机制,以便只使用像B树等索引机制从数据库中获取那些记录(第100个第200个)?
解决方法
select * from <table_name>;
没有第100行到第200行,因为你没有指定ORDER BY.订单无法保证,除非您出于很多有趣的原因包含ORDER BY,但这不是真正的重点.
为了说明你的观点,让我们使用一个表 – 我将使用Stack Overflow data dump中的Users表,并运行此查询:
SELECT * FROM dbo.Users ORDER BY DisplayName;
默认情况下,DisplayName字段上没有索引,因此sql Server必须扫描整个表,然后按DisplayName对其进行排序. Here’s the execution plan:
这不是很好 – 这是很多工作,估计的子树成本约为3万. (你可以通过将鼠标悬停在PasteThePlan上的select运算符上来看到它.)那么,如果我们只想要行100-200,会发生什么?我们可以在sql Server 2012中使用此语法:
SELECT * FROM dbo.Users ORDER BY DisplayName OFFSET 100 ROWS FETCH NEXT 100 ROWS ONLY;
The execution plan on that也很难看:
sql Server仍在扫描整个表以构建排序列表,只是为了给你100-200行,成本仍然在30k左右.更糟糕的是,每次运行查询时都会重建整个列表(因为毕竟有人可能已经更改了它们的DisplayName.)
为了使它更快,我们可以在DisplayName上创建一个非聚集索引,它是我们表的副本,按该特定字段排序:
CREATE INDEX IX_DisplayName ON dbo.Users(DisplayName);
使用该索引,our query’s execution plan现在执行索引:
查询立即完成,估计的子树成本仅为0.66(而不是30k).
总之,如果您以支持经常运行的查询的方式组织数据,那么是的,sql Server可以使用快捷方式使您的查询更快.另一方面,如果你拥有的只是堆或聚集索引,那么你就搞砸了.