• MSSQL执行计划重用


    --简介

    在Oracle的世界里有很多存储执行计划的手段如SQL_Profile, Stored_Outline, Plan_Baseline,在SQL Server里好像只有这样一个选择

    --Ref

    1.http://technet.microsoft.com/zh-cn/library/cc966425(en-us).aspx
      --Batch Compilation, Recompilation, and Plan Caching Issues in SQL Server 2005
    2.《SQL Server 2005 Practical Troubleshooting The Database Engine》Chapter 4
       本页下方有一个使用例子是从这本书上摘录的

    --自己创建执行计划

    • 建立存储过程
      代码 
    • sp_create_plan_guide
      sp_create_plan_guide
      @name = N'Guide1',
      @stmt = N'SELECT *FROM Sales.SalesOrderHeader AS h,
      Sales.Customer AS c,
      Sales.SalesTerritory AS t
      WHERE h.CustomerID = c.CustomerID
      AND c.TerritoryID = t.TerritoryID
      AND CountryRegionCode = @Country_region
      ',
      @type = N'OBJECT',
      @module_or_batch = N'Sales.GetSalesOrderByCountry',
      @params = NULL,
      @hints = N'OPTION (OPTIMIZE FOR (@Country_region = N''US''))'
      --其中@Country_region = N''US''查询较多,所以以下plan把us为参数的语句放到缓存Buffer中
      @hints = N'OPTION (PARAMETERIZATION FORCED)'
      --其中PARAMETERIZATION FORCED把带参数所有语句都放到缓存Buffer中 
    • sp_get_query_template:按照特定的语句生成template,之后生成执行计划
      --Obtain the paramaterized form of the query:
      DECLARE @stmt nvarchar(max);
      DECLARE @params nvarchar(max);
      EXEC sp_get_query_template N'SELECT pi.ProductID, SUM(pi.Quantity) AS Total
      FROM Production.ProductModel pm
      INNER JOIN Production.ProductInventory pi
      ON pm.ProductModelID = pi.ProductID
      WHERE pi.ProductID = 101
      GROUP BY pi.ProductID, pi.Quantity
      HAVING SUM(pi.Quantity) > 50
      ',
      @stmt OUTPUT,
      @params OUTPUT;
      --Force parameterization of the query. (This step is only required
      --
      if the query is not already being parameterized.)

      EXEC sp_create_plan_guide N'TemplateGuide1',
      @stmt,
      N
      'TEMPLATE',
      NULL,
      @params,
      N
      'OPTION(PARAMETERIZATION FORCED)';
      --Create a plan guide on the parameterized query

      EXEC sp_create_plan_guide N'GeneralizedGuide1',
      @stmt,
      N
      'SQL',
      NULL,
      @params,
      N
      'OPTION(HASH JOIN)'; --强制进行Hash Join

    --从缓存(sys.dm_exec_query_stats)中的查询计划内创建执行计划

    • sp_create_plan_guide_from_handle
      USE AdventureWorks;
      GO
      SELECT WorkOrderID, p.Name, OrderQty, DueDate
      FROM Production.WorkOrder AS w
      JOIN Production.Product AS p ON w.ProductID = p.ProductID
      WHERE p.ProductSubcategoryID > 4
      ORDER BY p.Name, DueDate;
      GO
      -- Inspect the query plan by using dynamic management views.

      SELECT * FROM sys.dm_exec_query_stats AS qs
      CROSS APPLY sys.dm_exec_sql_text(sql_handle)
      CROSS APPLY sys.dm_exec_text_query_plan(qs.plan_handle, qs.statement_start_offset, qs.statement_end_offset) AS qp
      WHERE text LIKE N'SELECT WorkOrderID, p.Name, OrderQty, DueDate%';
      GO
      -- Create a plan guide for the query by specifying the query plan in the plan cache.

      DECLARE @plan_handle varbinary(64);
      DECLARE @offset int;
      SELECT @plan_handle = plan_handle, @offset = qs.statement_start_offset
      FROM sys.dm_exec_query_stats AS qs
      CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS st
      CROSS APPLY sys.dm_exec_text_query_plan(qs.plan_handle, qs.statement_start_offset, qs.statement_end_offset) AS qp
      WHERE text LIKE N'SELECT WorkOrderID, p.Name, OrderQty, DueDate%';

      EXECUTE sp_create_plan_guide_from_handle
      @name = N'Guide1',
      @plan_handle = @plan_handle,
      @statement_start_offset = @offset;
      GO
      -- Verify that the plan guide is created.
      SELECT * FROM sys.plan_guides
      WHERE scope_batch LIKE N'SELECT WorkOrderID, p.Name, OrderQty, DueDate%';
      GO 
    • 为多语句批处理创建多个计划指南
      USE AdventureWorks;
      GO
      SELECT * FROM Production.Product WHERE ProductSubcategoryID > 4;
      SELECT * FROM Person.Address;
      SELECT * FROM Production.Product WHERE ProductSubcategoryID > 10;
      GO

      -- Examine the query plans for this batch

      SELECT * FROM sys.dm_exec_query_stats AS qs
      CROSS APPLY sys.dm_exec_sql_text(sql_handle)
      CROSS APPLY sys.dm_exec_text_query_plan(qs.plan_handle, qs.statement_start_offset, qs.statement_end_offset) AS qp
      WHERE text LIKE N'SELECT * FROM Production.Product WHERE ProductSubcategoryID > 4%';
      GO

      -- Create plan guides for the first and third statements in the batch by specifying the statement offsets.

      BEGIN TRANSACTION

      DECLARE @plan_handle varbinary(64);
      DECLARE @offset int;

      SELECT @plan_handle = plan_handle, @offset = qs.statement_start_offset
      FROM sys.dm_exec_query_stats AS qs
      CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS st
      CROSS APPLY sys.dm_exec_text_query_plan(qs.plan_handle, qs.statement_start_offset, qs.statement_end_offset) AS qp
      WHERE text LIKE N'SELECT * FROM Production.Product WHERE ProductSubcategoryID > 4%'
      AND SUBSTRING(st.text, (qs.statement_start_offset/2) + 1,
      ((
      CASE statement_end_offset
      WHEN -1 THEN DATALENGTH(st.text)
      ELSE qs.statement_end_offset END
      - qs.statement_start_offset)/2) + 1) like 'SELECT * FROM Production.Product WHERE ProductSubcategoryID > 4%'

      EXECUTE sp_create_plan_guide_from_handle
      @name = N'Guide_Statement1_only',
      @plan_handle = @plan_handle,
      @statement_start_offset = @offset;

      SELECT @plan_handle = plan_handle, @offset = qs.statement_start_offset
      FROM sys.dm_exec_query_stats AS qs
      CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS st
      CROSS APPLY sys.dm_exec_text_query_plan(qs.plan_handle, qs.statement_start_offset, qs.statement_end_offset) AS qp
      WHERE text LIKE N'SELECT * FROM Production.Product WHERE ProductSubcategoryID > 4%'
      AND SUBSTRING(st.text, (qs.statement_start_offset/2) + 1,
      ((
      CASE statement_end_offset
      WHEN -1 THEN DATALENGTH(st.text)
      ELSE qs.statement_end_offset END
      - qs.statement_start_offset)/2) + 1) like 'SELECT * FROM Production.Product WHERE ProductSubcategoryID > 10%'

      EXECUTE sp_create_plan_guide_from_handle
      @name = N'Guide_Statement3_only',
      @plan_handle = @plan_handle,
      @statement_start_offset = @offset;

      COMMIT TRANSACTION
      GO

      -- Verify the plan guides are created.

      SELECT * FROM sys.plan_guides;
      GO

    --删除,启用或禁用执行计划

    • 删除、启用或禁用计划指南 -- sp_control_plan_guide
      --Create a procedure on which to define the plan guide.
      IF OBJECT_ID(N'Sales.GetSalesOrderByCountry', N'P') IS NOT NULL
      DROP PROCEDURE Sales.GetSalesOrderByCountry;
      GO
      CREATE PROCEDURE Sales.GetSalesOrderByCountry
      (
      @Country nvarchar(60))
      AS
      BEGIN
      SELECT *
      FROM Sales.SalesOrderHeader AS h
      INNER JOIN Sales.Customer AS c ON h.CustomerID = c.CustomerID
      INNER JOIN Sales.SalesTerritory AS t ON c.TerritoryID = t.TerritoryID
      WHERE t.CountryRegionCode = @Country;
      END
      GO

      --Create the plan guide.
      EXEC sp_create_plan_guide N'Guide3',
      N
      'SELECT *
      FROM Sales.SalesOrderHeader AS h
      INNER JOIN Sales.Customer AS c ON h.CustomerID = c.CustomerID
      INNER JOIN Sales.SalesTerritory AS t ON c.TerritoryID = t.TerritoryID
      WHERE t.CountryRegionCode = @Country
      ',
      N
      'OBJECT',
      N
      'Sales.GetSalesOrderByCountry',
      NULL,
      N
      'OPTION (OPTIMIZE FOR (@Country = N''US''))';
      GO
      --Disable the plan guide.
      EXEC sp_control_plan_guide N'DISABLE', N'Guide3';
      GO
      --Enable the plan guide.
      EXEC sp_control_plan_guide N'ENABLE', N'Guide3';
      GO
      --Drop the plan guide.
      EXEC sp_control_plan_guide N'DROP', N'Guide3';
    • 禁用当前数据库中的所有计划指南
      USE AdventureWorks;
      GO
      EXEC sp_control_plan_guide N'DISABLE ALL';

    --一个例子(忘了是从哪里看到的,没修改就放到这里了)

    • 1 制造分散数据
      代码
    • 2 开始测试
      DBCC FREEPROCCACHE
      SET STATISTICS IO ON
      SET STATISTICS TIME ON

      EXEC sp 2
      /*SQL Server 分析和编译时间:CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
      SQL Server 分析和编译时间:CPU 时间 = 0 毫秒,占用时间 = 2 毫秒。
      表 't'。扫描计数 1,逻辑读取 6 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
      SQL Server 执行时间:CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
      SQL Server 执行时间:CPU 时间 = 0 毫秒,占用时间 = 2 毫秒。
      */
      EXEC sp 2
      /*SQL Server 分析和编译时间:CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
      SQL Server 分析和编译时间:CPU 时间 = 0 毫秒,占用时间 = 2 毫秒。
      表 't'。扫描计数 1,逻辑读取 786890 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
      SQL Server 执行时间:CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
      SQL Server 执行时间:CPU 时间 = 0 毫秒,占用时间 = 2 毫秒。
      */

      Alter proc sp @i int as select c2,c3 from t where c2 = @i Option (Optimize for (@i = 1));

      EXEC sp_create_plan_guide
      @Name=N'Guide1',
      @stmt = N'SELECT c2,c3 FROM t WHERE c2=@i',
      @type = N'OBJECT',
      @module_or_batch = N'dbo.sp',
      @params=NULL,
      @hints=N'OPTION (OPTIMIZE FOR (@i = 1))'
      GO

      SET SHOWPLAN_XML ON;
      GO
      select c2,c3 from t where c2 = 1
      go
      SET SHOWPLAN_XML OFF;

      --在查询配置中,直接使用该查询计划,如:
      EXEC sp_create_plan_guide @Name=N'Guide1',
      @stmt = N'SELECT c2,c3 FROM t WHERE c2=@i',
      @type = N'OBJECT',
      @module_or_batch = N'dbo.sp',
      @params=NULL,
      @hints=N'OPTION (USE PLAN
      N
      '上一个脚本的XML结果')'
      采用上述的作法直接影响SQL SERVER编译执行计划的方式,但如同各种数据表提示(hint),非得不得已不要轻易使用;使用上述查询计划,适用1,但用户又偏好2,则上述配置则反而有害了;
  • 相关阅读:
    Number Clicker CodeForces
    We Need More Bosses CodeForces
    Tree Constructing CodeForces
    Berland and the Shortest Paths CodeForces
    Allowed Letters CodeForces
    Military Problem CodeForces
    FFT自看
    Communication System
    Dollars
    Coin Change
  • 原文地址:https://www.cnblogs.com/buro79xxd/p/1703085.html
Copyright © 2020-2023  润新知