sql server 缓存

Whenever a query is run for the first time in SQL Server, it is compiled and a query plan is generated for the query. Every query requires a query plan before it is actually executed. This query plan is stored in SQL Server query plan cache. This way when that query is run again, SQL Server doesn’t need to create another query plan; rather it uses the cached query plan which improved database performance.

每当在SQL Server中首次运行查询时,都会对其进行编译并为该查询生成查询计划。 每个查询在实际执行之前都需要一个查询计划。 此查询计划存储在SQL Server查询计划缓存中。 这样,当再次运行该查询时,SQL Server无需创建另一个查询计划; 而是使用缓存的查询计划来提高数据库性能。

The duration that a query plan stays in the plan cache depends upon how often a query is executed. Query plans that are used more often, stay in the query plan cache for longer durations, and vice-versa.

查询计划在计划缓存中保留的持续时间取决于执行查询的频率。 使用频率更高的查询计划会在查询计划缓存中保留更长的时间,反之亦然。

In this article we will look at:

在本文中,我们将研究:

  • How to view the query plan cache 如何查看查询计划缓存
  • How to clear the plan cache 如何清除计划缓存
  • How to use parameterized queries to reuse query plans. 如何使用参数化查询重用查询计划。

如何查看SQL Server查询计划缓存 (How to view the SQL Server query plan cache)

SQL Server provides the following dynamic management views and functions that can be used to find out what is in the plan cache at any given time.

SQL Server提供以下动态管理视图和功能,这些视图和功能可用于在任何给定时间查找计划缓存中的内容。

  • sys.dm_exec_cached_plans sys.dm_exec_cached_plans
  • sys.dm_exec_sql_text sys.dm_exec_sql_text
  • sys.dm_exec_query_plan sys.dm_exec_query_plan

The first dm_exec_cached_plans is a dynamic management view while the remaining two are dynamic management functions.

第一个dm_exec_cached_plans是动态管理视图,其余两个是动态管理功能。

Let us use these functions and views to see what is in the SQL Server cached query plan. Execute the following query on your SSMS (SQL Server Management Studio):

让我们使用这些功能和视图来查看SQL Server缓存查询计划中的内容。 在SSMS(SQL Server Management Studio)上执行以下查询:

SELECT cplan.usecounts, cplan.objtype, qtext.text, qplan.query_plan
FROM sys.dm_exec_cached_plans AS cplan
CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS qtext
CROSS APPLY sys.dm_exec_query_plan(plan_handle) AS qplan
ORDER BY cplan.usecounts DESC

A SELECT statement is used to select usecounts, object type, query text and an XML representation of the query plan of all the queries that currently reside in the query plan cache. Notice that the CROSS APPLY operator has been used to join the output from dynamic management views and functions. Finally, the result set is sorted in the descending order of the use counts. The output on my machine looks like this (It may differ on your machine depending upon the queries that reside in your query plan):

SELECT语句用于选择使用计数,对象类型,查询文本以及当前驻留在查询计划缓存中的所有查询的查询计划的XML表示形式。 请注意,已使用CROSS APPLY运算符将动态管理视图和功能的输出联接在一起 。 最后,结果集按使用次数的降序排序。 我的计算机上的输出如下所示(根据您的查询计划中的查询,您的计算机上的输出可能会有所不同):

Here the usecount column contains a count for the number of times a query has been executed. The objtype column contains information about the object through which a query is executed. It is important to mention that up till SQL Server 6.5 only stored procedure queries were stored in the cached plan. From SQL Server 7.0 onwards, dynamic and ad-hoc queries are also stored in the cached plan. The text column contains the text of the query and finally, the query_plan column contains the XML representation of the query. Click any row in the query_plan column to see the detailed XML representation of the plan.

此处usecount列包含查询执行次数的计数。 objtype列包含有关通过其执行查询的对象的信息。 重要的是要提到,直到SQL Server 6.5为止,只有存储过程查询存储在缓存的计划中。 从SQL Server 7.0起,动态查询和即席查询也存储在缓存的计划中。 text列包含查询的文本,最后,query_plan列包含查询的XML表示形式。 单击query_plan列中的任何行以查看该计划的详细XML表示形式。

清除计划缓存 (Clearing the plan cache)

To clear the plan cache, execute the following:

要清除计划缓存,请执行以下操作:

DBCC FREEPROCCACHE

存储过程查询计划 (Stored procedure query plan)

Now let’s execute a simple stored procedure and see what we get in our SQL Server query plan cache.

现在,让我们执行一个简单的存储过程,看看我们在SQL Server查询计划缓存中得到了什么。

First let’s create a dummy database and a table inside that database:

首先,我们创建一个虚拟数据库和该数据库内的表:

CREATE Database company;USE company;CREATE TABLE department
(id INT PRIMARY KEY,dep_name VARCHAR(50) NOT NULL,)

Next insert some records into the table:

接下来将一些记录插入表中:

USE company;INSERT INTO department VALUES
(1, 'Sales'),
(2, 'HR'),
(3, 'IT'),
(4, 'Marketing'),
(5, 'Finance')

Finally, let’s create a simple stored procedure that retrieves all the records from the department table of the company database:

最后,让我们创建一个简单的存储过程,该存储过程从公司数据库的部门表中检索所有记录:

USE company
GOCREATE PROCEDURE getdepartment
AS
SELECT * FROM department
GO

Before we execute the getdepartment stored procedure, clear the query plan cache using following query:

在执行getdepartment存储过程之前,请使用以下查询清除查询计划缓存:

CREATE Database company;

Now, execute the newly created getdepartment stored procedure:

现在,执行新创建的getdepartment存储过程:

exec getdepartment

Once the stored procedure is executed, try to retrieve the information about all the query plans in the plan cache, again execute the following query:

一旦执行了存储过程,请尝试在计划缓存中检索有关所有查询计划的信息,然后再次执行以下查询:

SELECT cplan.usecounts, cplan.objtype, qtext.text, qplan.query_plan
FROM sys.dm_exec_cached_plans AS cplan
CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS qtext
CROSS APPLY sys.dm_exec_query_plan(plan_handle) AS qplan
ORDER BY cplan.usecounts DESC

When the above query is executed, you will see that two query plans will be retrieved: One query plan for the stored procedure and the other for the query that retrieves the query plan. The output looks like this:

执行上述查询后,您将看到将检索两个查询计划:一个用于存储过程的查询计划,另一个用于检索该查询计划的查询。 输出看起来像这样:

In the first row, you can see the object type Proc. This refers to the stored procedure query plan that we just executed. Inside the text column, you can also see the information about the stored procedure and the actual query that we executed inside the stored procedure.

在第一行中,您可以看到对象类型Proc。 这是指我们刚刚执行的存储过程查询计划。 在文本列中,您还可以查看有关存储过程的信息以及我们在存储过程中执行的实际查询。

Here the usecount column displays the number of times query is executed. Execute the stored procedure once more and then retrieve the query plan cache, and you will see following results:

这里的usecount列显示查询执行的次数。 再次执行存储过程,然后检索查询计划缓存,您将看到以下结果:

You can see that count for both the stored procedure and the query plan access queries have jumped to 2.

您可以看到存储过程和查询计划访问查询的计数已跃升至2。

查询计划取决于查询文本 (The query plan depends upon the query text)

SQL Server generates a query plan using a hash value that is calculated from the query text. When a query is run, SQL Server calculates its hash value and checks if a plan with the same hash value exists in the plan cache. If a plan with same hash value exists, that plan is executed. However, if a plan with the newly calculated hash value doesn’t exist, a new query plan is generated and stored in the cache plan.

SQL Server使用从查询文本计算得出的哈希值来生成查询计划。 运行查询时,SQL Server将计算其哈希值,并检查计划缓存中是否存在具有相同哈希值的计划。 如果存在具有相同哈希值的计划,则将执行该计划。 但是,如果不存在具有新计算的哈希值的计划,则会生成一个新的查询计划并将其存储在缓存计划中。

The hash value for the query plan is generated from the text. Therefore if there is even a slight change in the query text (e.g. a change of case, comma or space) a new hash value will be generated and thus a new query plan. Let’s see an example of this.

查询计划的哈希值是从文本生成的。 因此,即使查询文本有微小变化(例如大小写,逗号或空格的变化),也会生成新的哈希值,从而生成新的查询计划。 让我们来看一个例子。

Clear the query plan cache and execute the following query twice:

清除查询计划缓存,并两次执行以下查询:

SELECT * FROM department where dep_name = 'Sales'

When you retrieve the query plan cache, you can see that usecount for the Adhoc query that we just executed twice is 2:

检索查询计划缓存时,您可以看到我们刚刚执行了两次的Adhoc查询的usecount为2:

Now let’s make a slight change to our query:

现在,让我们对查询进行一些更改:

SELECT * FROM department Where dep_name = 'Sales'

Here we have replaced small case w of the where clause from the previous query to capital case W. This is a minor change, but when the above query is executed a new hash value is calculated and hence a new query plan is generated for the query. If you look at the query cash plan now, you will see following output:

在这里,我们将前一个查询的where子句的小写字母w替换为大写字母W。 这是一个较小的更改,但是当执行以上查询时,将计算新的哈希值,因此将为该查询生成新的查询计划。 如果现在查看查询现金计划,您将看到以下输出:

From the output, you can see that there are two query plans with same functionality but different text.

从输出中,您可以看到有两个具有相同功能但文本不同的查询计划。

Similarly, if you change the value from the dep_name from Sales to HR, a new query plan will be generated.

同样,如果将值从dep_name从Sales更改为HR,将生成一个新的查询计划。

使用参数化查询以实现可重用性 (Use parameterized queries for reusability)

We know that when a query’s text changes, a new query plan is generated instead of reusing the existing one. Parameterized queries resolve this issue. In a parameterized query we pass dynamic values in the form of parameters to the query. The query text itself doesn’t change; therefore existing query plans can be reused instead of creating a new plan. Let’s take a look at a simple example.

我们知道,当查询的文本更改时,将生成一个新的查询计划,而不是重用现有的查询计划。 参数化查询可解决此问题。 在参数化查询中,我们将参数形式的动态值传递给查询。 查询文本本身不变。 因此,可以重复使用现有的查询计划,而不用创建新的计划。 让我们看一个简单的例子。

Let’s create a parameterized stored procedure that retrieves the department record by name. Execute the following query:

让我们创建一个参数化的存储过程,该存储过程按名称检索部门记录。 执行以下查询:

USE company
GOCREATE PROCEDURE getdepartmentbyname @name nvarchar(30)
AS
SELECT * FROM department WHERE dep_name = @name
GO

The above stored procedure filters department records using department name passed as parameters. Now clear the query plan cache and execute the following stored procedure:

上面的存储过程使用作为参数传递的部门名称来过滤部门记录。 现在,清除查询计划缓存并执行以下存储过程:

exec getdepartmentbyname 'Sales'

Execute the getdepartmentbyname stored procedure again but with different parameters this time:

再次执行getdepartmentbyname存储过程,但是这次使用不同的参数:

exec getdepartmentbyname 'HR'

Now if you retrieve the values from the query plan cache you will see that although you executed the stored procedure twice with different text, there is only one plan for the stored procedure getdepartmentbyname and its usecount is 2 which means that the plan has been executed twice:

现在,如果您从查询计划缓存中检索值,您将看到尽管您使用不同的文本执行了两次存储过程,但是存储过程getdepartmentbyname只有一个计划,其usecount为2,这意味着该计划已执行了两次:

This shows that using parameterized queries, you can reuse the existing query plans despite changing query text.

这表明使用参数化查询,尽管更改了查询文本,仍可以重用现有查询计划。

本的其他精彩文章 (Other great articles from Ben)

How SQL Server selects a deadlock victim
Identifying Object Dependencies in SQL Server Management Studio
Understanding SQL Server query plan cache
SQL Server如何选择死锁受害者
在SQL Server Management Studio中识别对象依赖性
了解SQL Server查询计划缓存

翻译自: https://www.sqlshack.com/understanding-sql-server-query-plan-cache/

sql server 缓存

sql server 缓存_了解SQL Server查询计划缓存相关推荐

  1. sql server 缓存_搜索SQL Server查询计划缓存

    sql server 缓存 Whenever a query is executed in SQL Server, its execution plan, as well as some useful ...

  2. sql server 统计_看SQL Server 2016中的新实时查询统计信息

    sql server 统计 With the release of SQL Server 2016 also comes a great new feature to get a live view ...

  3. sql server 循环_学习SQL:SQL Server循环简介

    sql server 循环 Loops are one of the most basic, still very powerful concepts in programming – the sam ...

  4. sql server序列_在SQL Server中实现序列聚类

    sql server序列 In this article, we will be discussing Microsoft Sequence Clustering in SQL Server. Thi ...

  5. sql server作业_在SQL Server中报告作业失败并发出警报

    sql server作业 SQL Server Agent can be used to run a wide variety of tasks within SQL Server. The buil ...

  6. sql server调试_使用SQL Server扩展事件来调试应用程序

    sql server调试 介绍 (Introduction) Often enough, multilayer software has bugs. SQL Server Extended Event ...

  7. sql server版本号_识别SQL Server版本号的不同方法

    sql server版本号 In this article, I am going to show different methods to identify the SQL Server versi ...

  8. sql server死锁_了解SQL Server中的死锁图的XML描述

    sql server死锁 介绍 (Introduction) 在我的前两篇文章" What is a SQL Server Deadlock and 什么是SQL Server死锁" ...

  9. sql server死锁_了解SQL Server死锁图的图形表示

    sql server死锁 #contentor img { float: left; } #contentor img { float: left; } 介绍 (Introduction) If yo ...

最新文章

  1. 三层架构 || SpringMVC 和 Struts2 的优略分析
  2. js 定时网页点击_JS的小乐趣:轻松完成打地鼠游戏
  3. 网站随机动态密码代码
  4. 微型计算机电路基础第四版逻辑门,数字逻辑的电路基础——逻辑门.PDF
  5. 用Eclipse创建一个spring boot(连接mysql,简单使用mybatis)
  6. 数据库程序设计复习资料
  7. python发短信sim800_sim800a发短信流程
  8. JAVA多线程是什么
  9. 【软件测试】使用C++ Test 进行静态测试
  10. 最新第一波:全国信息化工程师软考-系统集成项目管理工程师(高级案例高分论文)
  11. 因子分解机(FM,FFM,DeepFM,libfm,xlearn)
  12. originPro2021(7)导出图表不清晰
  13. 第 46 届 ICPC 国际大学生程序设计竞赛亚洲区域赛(沈阳)
  14. 如何解决Win10电脑网速慢的问题?
  15. 51单片机教程:51单片机驱动四个8*8点阵,拼凑16*16点阵显示标准汉字。
  16. 数学之美:常用的微分,求导和积分公式大总结
  17. 国家杰青,任同济大学新校长!
  18. 【 MATLAB 】离散傅里叶变换(DFT)以及逆变换(IDFT)的MATLAB实现
  19. 计算机主机机箱背后,2.8L的办公电脑?可以背在显示器后面的主机—你见过吗?...
  20. OneNote无法登录 遇到临时服务器问题

热门文章

  1. java消息推送怎么实现_PHP实现的消息实时推送功能
  2. 35张史上最全IT架构师技术知识图谱
  3. jQuery多选列表框插件Multiselect
  4. QTP 自动化测试--定义变量
  5. 《SQL Server 2008从入门到精通》--20180703
  6. [转]Java8 Lambda表达式教程
  7. c#利用zlib.net对文件进行deflate流压缩(和java程序压缩生成一样)
  8. 重构我的CMS系统,增加ORM
  9. android ndk 多线程mk,Android NDK 开发教程六: application.mk
  10. 每天开豪车跟随老板出入高档会所,吃住高档酒店,这样的职场生活,有必要坚持下去吗?