Plan zorlama senaryosu: Yeniden bir sorgudan alınan bir Plan zorlamak için bir Plan kılavuz oluşturmak
Sık sık sorgu için geliştirilmiş bir planı elde etmek için en uygun sorgu sorgu mantıksal anlamını değiştirmeden Sorgu ipuçları kullanarak birleştirmek sırasını, birleştirmek algoritmalar veya dizin kullanımını zorlamak için el ile yeniden yazmak için yoludur.Sorgu içinde dağıtılmış bir uygulama ise, ancak, bu yöntem kullanılabilir olmayabilir.Plan kılavuzları kullanarak bu durumda yardımcı olabilir.Çalışma kılavuzları olası veya doğrudan sorgu metnini değiştirmek için uygun olmadığında sorgu ipuçları veya sorgu planları sorguları ekleyerek planlayın.Daha fazla bilgi için bkz: Plan kılavuzları kullanarak sorgular dağıtılan uygulamalar içinde en iyi duruma getirme.
El ile bir sorgu el ile yeniden plandan yakalamak ve sonra özgün sorgu yakalanan planı içeren bir plan Kılavuzu ile yakalanan planı uygulamak için bu işlemi izleyin:
Sorguyu değiştirmek nasıl belirlenir (force order, birleştirmek ipuçları veya dizin ipuçlarını kullanarak, birleştirmek sırasını değiştirerek ve başka teknikler kullanan), böylece iyi bir plan üretilen ancak sorgunun mantıksal anlamı değişti.
Yalnızca özgün sorgu gibi gönderilen yeniden sorgu planı yakalama (gibi kullanarak sp_executesql, sp_cursorprepexec, ya da tek başına bir toplu iş olarak).
Özgün sorgu alınan iyi plan zorlamak için bir plan Kılavuzu oluşturun.
Kullanarak SQL Server Profiler, select Plan Kılavuzu başarılı ve Plan Kılavuzu başarısız olaylar Performans kategorisini ve sonra da özgün sorguyu çalıştırın.İnceleme SQL Server Profiler sorguyu kullandığını doğrulamak için plan kılavuzu.
Örnek
Aşağıdaki sorgu çok yavaş bir sorgu planı oluşturur varsayalım.
USE AdventureWorks2008R2;
GO
EXEC sp_executesql
@stmt = N'SELECT soh.SalesPersonID
,p.FirstName + '' '' + COALESCE(p.MiddleName, '''') + '' '' + p.LastName AS FullName
,e.JobTitle
,st.Name AS SalesTerritory
,soh.SubTotal
,YEAR(DATEADD(m, 6, soh.OrderDate)) AS FiscalYear
FROM Sales.SalesPerson AS sp
INNER JOIN Sales.SalesOrderHeader AS soh ON sp.BusinessEntityID = soh.SalesPersonID
INNER JOIN Sales.SalesTerritory AS st ON sp.TerritoryID = st.TerritoryID
INNER JOIN HumanResources.Employee AS e ON soh.SalesPersonID = e.BusinessEntityID
INNER JOIN Person.Person AS p ON e.BusinessEntityID = p.BusinessEntityID
WHERE st.[Group] = @p1',
@params = N'@p1 nvarchar(80)',
@p1 = N'North America';
GO
Aşağıdaki şekilde mantıksal olarak aynı olmasını sorgu yazabilirsiniz ancak farklı birleştirmek sipariş ile hangi zorlanır.
USE AdventureWorks2008R2;
GO
EXEC sp_executesql
@stmt = N'SELECT
soh.SalesPersonID
,p.FirstName + '' '' + COALESCE(p.MiddleName, '''') + '' '' + p.LastName AS FullName
,e.JobTitle
,st.Name AS SalesTerritory
,soh.SubTotal
,YEAR(DATEADD(m, 6, soh.OrderDate)) AS FiscalYear
FROM Sales.SalesPerson sp
INNER JOIN Sales.SalesOrderHeader soh ON sp.BusinessEntityID = soh.SalesPersonID
INNER JOIN Sales.SalesTerritory st ON sp.TerritoryID = st.TerritoryID
INNER JOIN HumanResources.Employee e ON soh.SalesPersonID = e.BusinessEntityID
INNER JOIN Person.Person p ON e.BusinessEntityID = p.BusinessEntityID
WHERE st.[Group] = @p1
OPTION (FORCE ORDER)',
@params = N'@p1 nvarchar(80)',
@p1 = N'North America';
GO
Özgün sorguyu yeniden sorgu planı zorlamak için bir plan kılavuz oluşturmak için bir değişken planında yakalamak ve plan Kılavuzu'nda değişken belirtmek deyim aşağıdaki kodda gösterildiği gibi.
DBCC FREEPROCCACHE;
GO
USE AdventureWorks2008R2;
GO
EXEC sp_executesql
@stmt = N'SELECT
soh.SalesPersonID
,p.FirstName + '' '' + COALESCE(p.MiddleName, '''') + '' '' + p.LastName AS FullName
,e.JobTitle
,st.Name AS SalesTerritory
,soh.SubTotal
,YEAR(DATEADD(m, 6, soh.OrderDate)) AS FiscalYear
FROM Sales.SalesPerson sp
INNER JOIN Sales.SalesOrderHeader AS soh ON sp.BusinessEntityID = soh.SalesPersonID
INNER JOIN Sales.SalesTerritory AS st ON sp.TerritoryID = st.TerritoryID
INNER JOIN HumanResources.Employee AS e ON soh.SalesPersonID = e.BusinessEntityID
INNER JOIN Person.Person AS p ON e.BusinessEntityID = p.BusinessEntityID
WHERE st.[Group] = @p1
OPTION (FORCE ORDER)',
@params = N'@p1 nvarchar(80)',
@p1 = N'North America';
GO
DECLARE @xml_showplan nvarchar(max);
SET @xml_showplan = (SELECT query_plan
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
CROSS APPLY sys.dm_exec_text_query_plan(qs.plan_handle, DEFAULT, DEFAULT) AS qp
WHERE st.text LIKE N'%Sales.SalesPerson%' AND st.text LIKE N'%OPTION (FORCE ORDER)%');
EXEC sp_create_plan_guide
@name = N'ForceOrderGuide1',
@stmt = N'SELECT
soh.SalesPersonID
,p.FirstName + '' '' + COALESCE(p.MiddleName, '''') + '' '' + p.LastName AS FullName
,e.JobTitle
,st.Name AS SalesTerritory
,soh.SubTotal
,YEAR(DATEADD(m, 6, soh.OrderDate)) AS FiscalYear
FROM Sales.SalesPerson AS sp
INNER JOIN Sales.SalesOrderHeader AS soh ON sp.BusinessEntityID = soh.SalesPersonID
INNER JOIN Sales.SalesTerritory ASst ON sp.TerritoryID = st.TerritoryID
INNER JOIN HumanResources.Employee ASe ON soh.SalesPersonID = e.BusinessEntityID
INNER JOIN Person.Person ASp ON e.BusinessEntityID = p.BusinessEntityID
WHERE st.[Group] = @p1',
@type = N'SQL',
@module_or_batch = NULL,
@params = N'@p1 nvarchar(80)',
@hints = @xml_showplan;
GO
SELECT * FROM sys.plan_guides;
GO
Özgün sorguyu çalıştırmadan önce bir izleme oluşturmak SQL Server Profiler ve olayları seçin Plan Kılavuzu başarılı ve Plan Kılavuzu başarısız dan Performans kategori.Özgün sorguyu çalıştırabilir ve doğrulamak sonuçlar sorgunun çıktısı olarak izleme.
USE AdventureWorks2008R2;
GO
EXEC sp_executesql
@stmt = N'SELECT
soh.SalesPersonID
,p.FirstName + '' '' + COALESCE(p.MiddleName, '''') + '' '' + p.LastName AS FullName
,e.JobTitle
,st.Name AS SalesTerritory
,soh.SubTotal
,YEAR(DATEADD(m, 6, soh.OrderDate)) AS FiscalYear
FROM Sales.SalesPerson AS sp
INNER JOIN Sales.SalesOrderHeader AS soh ON sp.BusinessEntityID = soh.SalesPersonID
INNER JOIN Sales.SalesTerritory ASst ON sp.TerritoryID = st.TerritoryID
INNER JOIN HumanResources.Employee ASe ON soh.SalesPersonID = e.BusinessEntityID
INNER JOIN Person.Person AS p ON e.BusinessEntityID = p.BusinessEntityID
WHERE st.[Group] = @p1',
@params = N'@p1 nvarchar(80)',
@p1 = N'North America';
GO
Ayrıca bkz.