从我所有的搜索到加速sql server中的查询,源代表说通过使用正确的where子句来减少逻辑读取。 实际上我需要知道sql server中的存储过程如何从前端获得请求时的工作流程以及在存储过程中避免的一些提示,哪些不是。
答案 0 :(得分:39)
Microsoft白皮书是Retired SQL Server 2000 technical documentation(p387,最初来自SQL Server Architecture(SQL Server 2000))的一部分,它有一个很好的定义:
SQL Server实例的I / O分为逻辑I / O和物理I / O. 每次数据库引擎从缓冲区缓存请求页面时都会发生逻辑读取。如果页面当前不在缓冲区缓存中,则执行物理读取以将页面读入缓冲区缓存。如果页面当前在缓存中,则不会生成物理读取;缓冲区缓存只使用已经在内存中的页面。
因此,逻辑读取是指查询引擎需要读取数据的时间。首先,它在内存中看起来。如果页面已经在SQL Server的内存中,那么它就会使用它。如果它无法在内存中找到它,则会触发物理读取,并从磁盘读取数据页。没有后续物理读取的逻辑读取基本上是“缓存命中”。
缓冲区缓存(也称为缓冲池)是SQL Server用于解决查询的主要工作内存。设置SQL Server将使用的内存量时,您将控制可用缓冲区高速缓存的大小。
但是,告诉您在不查看查询或了解表中包含的内容以及数据的外观以及数据如何编制索引和组织的情况下您需要执行的操作基本上是不可能的。
大量的逻辑读取可能不一定是坏的 - 或者更确切地说,不一定是可预防的。什么是错误的过度数量的逻辑读取。如果你要返回3行数据,但是查询引擎必须扫描2亿行表来执行它,那将会非常慢,你可以通过重写查询或添加索引来改善它。
我首先要看一下存储过程中的查询有多复杂。值得注意的是,我会寻找丢失的索引。如果您正在运行SELECT * FROM BigTable WHERE ProductDate >= '01/01/2014'
,那么我会看到ProductDate
上有一个索引。但是,如果您正在运行SELECT * FROM BigTable ORDER BY ProductDate DESC
,那么,是的,索引仍然有用,但您仍然需要返回整个数据集,因此您无论如何都必须阅读整个表。另外,请注意逻辑读取是指 page 读取,因此如果所讨论的ProductDate
均匀分布在磁盘周围,则可能需要读取每个页面或几乎每个页面。
除此之外,可能是桌子上的统计数据已经过时了。如果你已经向表中添加了20,000行,而SQL Server仍然认为那里只有2000行,那么它将完全抛出查询计划。
答案 1 :(得分:21)
逻辑读取是指您从数据库中读取的记录。我们来看一个小而愚蠢的例子:
select *
from
(
select *
from orders
where client = 1234
)
where item = 9876;
在这里,您选择来自客户端1234的所有订单。然后您只需获取项目9876的订单。因此(如果优化器没有看到这一点并在内部优化您的查询)您在第一步中选择了比需要更多的记录。通过一步应用两个标准来减少逻辑读取(以及相应的大中间结果):
select *
from orders
where client = 1234
and item = 9876;
(这也可能会影响物理读取,但不一定非必要。例如,第一个查询可以访问100个记录,然后将其减少到10个,而第二个查询只读取10个。但是所有100个记录都可能在一个磁盘块,所以两个语句都读取一个磁盘块,即进行一次物理读取。顺便说一下,如果数据恰好已经在dbms缓存中,即在内存中,它甚至可以是零物理读取。这也告诉我们我们物理读取可能因查询而异,而逻辑读取只要查询和数据不被更改就保持不变。)