39

After doing my research, on how to speed up queries executed in SQL server, the majority of resources suggesting to reduce logical reads, by using the proper where clause. What I am really interested in is to know about the work flow in SQL server: when a stored procedure is being called by a request from an endpoint user or external system, and some tips on do's and don'ts'.

4

2 回答 2

54

来自Microsoft SQL Server Documentation (Pages and Extents Architecture -> Reading Pages) 有一个很好的定义:

来自 SQL Server 数据库引擎实例的 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,那么,是的,索引仍然会有所帮助,但是您仍然需要返回整个数据集,因此无论如何您都必须读取整个表。此外,请注意,逻辑读取指的是页面读取,因此如果有ProductDate问题的内容均匀分布在磁盘周围,您可能需要读取每一页或几乎每一页。

除此之外,可能是表上的统计信息已过时。如果您向表中添加了 20,000 行,而 SQL Server 仍然认为那里只有 2000 行,那么它将完全放弃查询计划。

于 2015-01-02T07:49:45.113 回答
39

逻辑读取意味着您正在从数据库中读取的记录。让我们举一个小而愚蠢的例子:

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 缓存中,即在内存中。这也告诉我们物理查询的读取可能会有所不同,而只要查询和数据未更改,逻辑读取就保持不变。)

于 2015-01-02T07:56:56.773 回答