Talk about the execution plan cache in SQL Server

Why do we need the execution plan cache?

From the introduction, we know that the process steps of generating the execution plan account for a large proportion, which will consume various CPU and memory resources. In fact, the query optimizer needs to do more work to generate the execution plan, which is roughly divided into three parts:

first, parse the table name, stored procedure name, view name, etc. according to the text of the incoming query statement. A tree representing the query text is then generated based on logical data operations.

The second step is optimization and simplification, such as converting subqueries into peer-to-peer joins, preferentially applying filter conditions, deleting unnecessary joins (for example, if there is an index, it may not need to refer to the original table), etc.

The third step is to perform a cost-based evaluation based on the statistical information in the database.

After the above three steps are completed, multiple candidate execution plans will be generated. Although we have only one SQL statement logically, there can be multiple physical data acquisition sequences that conform to this logical sequence. For example, if you want to go from Beijing to Shanghai, you can do high-speed rail or airplane. The description from Beijing to Shanghai is a logical description, and there are many ways to implement it. So let's look at another example in SQL Server, such as the query in Listing 1.

For this query, whether A joins B first or Inner Join C first, the result is the same, so multiple execution plans can be generated, but a basic principle is that SQL Server does not necessarily choose the best execution plan. Instead, choose a plan that is good enough, since the cost of evaluating the cost of all execution plans should not be too large. Ultimately, SQL Server will evaluate the cost of the execution plan based on the cardinality of the data and the cost of CPU and IO consumed by each step, so the choice of the execution plan is heavily dependent on statistical information. I will not elaborate on the relevant content of statistical information. .

It is not difficult to see the process of generating the execution plan by the query analyzer above, and the resource cost consumed by this step is also staggering. Therefore, when the same query is executed once, caching it will greatly reduce the compilation of the execution plan, thereby improving the efficiency. This is the original intention of the execution plan cache.

Objects cached by the execution plan

The objects cached by the execution plan are divided into four categories:

compiled plan: the relationship between the compiled execution plan and the execution plan is the same as the relationship between MSIL and C#.

Execution context: When executing a compiled plan, there is a context. Because the compiled plan can be shared by multiple users, but the query needs to store SET information and the value of local variables, etc., so the context environment needs to be associated with the execution plan. Execution context is also known as Executable Plan.

Cursor: The stored cursor state is similar to the implementation of the relationship between the price and picture below and the compiled plan. The cursor itself can only be used by a connection, but the execution plan associated with the cursor can be shared by multiple users.

Algebraic Trees: Algebraic trees (also known as parse trees) represent query text. As we said before, the query analyzer doesn't refer to the query text directly, but the algebraic tree. You may have questions here. The algebraic tree is used to generate the execution plan, and the algebraic tree trunk is also cached here? This is because views, defaults, constraints may be reused by different queries, and caching the algebraic tree of these objects saves the parsing process.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326674541&siteId=291194637