今天重新翻了翻自己的一些以前看过的关于数据库性能调优资料,发现一些东西,在这里晒晒,分享一下。
先总结一下经验吧。
一般情况下,当发现对一些数据表(多表)查询(包括SQL语句中的复杂查询与存储过程中的复杂查询)的效率上出现问题的时候,首先需要注意的,便是,这些表的索引是否已经创建,如果有创建,那这些索引创建的是否正确。造成效率不高的原因在哪里(哪张表的数据量大,导致性能降低)
如何查看自己创建的索引是否正确?(如果有做过性能优化的同学应该会立刻想到,使用执行计划。)
这里面就涉及到一些基本概念了。首先,大家都知道索引是分聚集索引和非聚集索引的,在Microsoft SQL Server中,要创建非聚集索引,一定是需要一个聚集索引的。
在一般的情况下,聚集索引列即主键列,但在大多数的情况下,主键作为聚集索引列,这是一种浪费,那哪种类型的列可以作为聚集索引列呢?
聚集索引与非聚集索引的区别中有提到的非常详细,这里便不再多提。
那平常的非聚集索引呢?需要验证非聚集索引正确与否?看看下面这个简单的示例:
对于我们需要优化的表A的查询语句where条件中,A表中涉及到的字段,C1,C2两个字段,当其关于为and时,使用索引是有效的,则我们可对这两个字段创建索引(当然,这其中涉及到了单字段索引和组合索引,这些要视情况而定。绝大部分情况下是使用单字段索引)。创建完索引后,此时,我们需要对索引进行验证。于是,set statistics io选项便非常有用了。在TeachNet中的解释为“使 SQL Server 显示有关由 Transact-SQL 语句生成的磁盘活动量的信息。”
set statistics io on |
执行了以上示例语句,我们可以查看到对应的查询结果,同时,我们可以在消息栏中查看到以下信息
这些信息中各个字段的意义,都有其相应的意义(以下来自引用):
扫描计数(Scan Count):在查询中涉及到的表被访问的次数。在我们的例子中,其中的表只被访问了1次,由于查询中不包括连接命令,这一信息并不是十分有用,但如果查询中包含有一个或多个连接,则这一信息是十分有用的。(一个循环外部的表的Scan Count值为1,但对于一个循环内的表而言,其值为循环的次数。可以想象得到,对于一个循环内的表而言,其Scan Count值越小,它所使用的资源越少,查询的性能也就越高。因此在调节一个带连接的查询的性能时,需要关注Scan Count的值,在进行调节时,注意观察它是增加还是减少了。)
逻辑读取(Logical Reads):这是SET STATISTICS IO或SET STATISTICS TIME命令提供的最有用的 数据。我们知道,SQL Server在可以对任何数据进行操作前,必须首先把数据读取到其数据缓冲区中。此外,我们也知道SQL Server何时会从数据缓冲区中读取数据,并把数据读取到大小为8K字节的页中。那么Logical Reads的意义是什么呢?Logical Reads是指SQL Server为得到查询中的结果而必须从数据缓冲区读取的页数。在执行查询时,SQL Server不会读取比实际需求多或少的数据,因此,当在相同的数据集上执行同一个查询,得到的Logical Reads的数字总是相同的。(SQL Server执行查询时的Logical Reads值每一次这个数值是不会变化的。因此,在进行查询性能的调节时,这是一个可以用来衡量你的调节措施是否成功的一个很好的标准。如果 Logical Reads值下降,就表明查询使用的服务器资源减少,查询的性能有所提高。如果Logical Reads值增加,则表示调节措施降低了查询的性能。在其他条件不变的情况下,一个查询使用的逻辑读越少,其效率就越高,查询的速度就越快。)
物理读取(Physical Reads):物理读,在执行真正的查询操作前,SQL Server必须从磁盘上向数据缓冲区中读取它所需要的数据。在SQL Server开始执行查询前,它要作的第一件事就是检查它所需要的数据是否在数据缓冲区中,如果在,就从中读取,如果不在,SQL Server必须首先将它需要的数据从磁盘上读到数据缓冲区中。我们可以想象得到,SQL Server在执行物理读时比执行逻辑读需要更多的服务器资源。因此,在理想情况下,我们应当尽量避免物理读操作。下面的这一部分听起来让人容易感到糊涂 了。在对查询的性能进行调节时,可以忽略物理读而只专注于逻辑读。你一定会纳闷儿,刚才不是还说物理读比逻辑读需要更多的服务器资源吗?情况确实是这样, SQL Server在执行查询时所需要的物理读次数不可能通过性能调节而减少的。减少物理读的次数是DBA的一项重要工作,但它涉及到整个服务器性能的调节,而 不仅仅是查询性能的调节。在进行查询性能调节时,我们不能控制数据缓冲区的大小或服务器的忙碌程度以及完成查询所需要的数据是在数据缓冲区中还是在磁盘 上,唯一我们能够控制的数据是得到查询结果所需要执行的逻辑读的次数。
因此,在查询性能的调节中,我们可以心安理得地不理会SET STATISTICS IO命令提供的Physical Read的值。(减少物理读次数、加快SQL Server运行速度的一种方式是确保服务器的物理内存足够多。)
预计(Read-Ahead Reads):与Physical Reads一样,这个值在查询性能调节中也没有什么用。Read-Ahead Reads表示SQL Server在执行预读机制时读取的物理页。为了优化其性能,SQL Server在认为它需要数据之前预先读取一部分数据,根据SQL Server对数据需求预测的准确程度,预读的数据页可能有用,也可能没用。
一般在数据库的查询优化过程中,Logic Read是至关重要的,它的计数一般与查询出来的结果集数量成正比,与数据读取的速度也成正比。因此,我们便可以从中看出整个查询(复杂语句,包括存储过程等)中的瓶颈所在,从而进行优化。